Re: [PATCH V2 1/2] Input: of_keymap: Introduce matrix_keypad_of_build_keymap()
On 3/29/2012 2:58 AM, Stephen Warren wrote: > so the DT parsing can easily overflow this, and is driven by > user-supplied data. Got it. This check is must. > I think you'll need to pass input_dev->keycodesize you mean keycodemax here? > into matrix_keypad_of_build_keymap() to achieve the overall > range-checking. Will do that. > but also checking col against (1< needed to make sure the individual "fields" of the array index don't > overflow too. Ok. Please cross check V3 to verify, i got you comments correctly. -- viresh ___ devicetree-discuss mailing list devicetree-discuss@lists.ozlabs.org https://lists.ozlabs.org/listinfo/devicetree-discuss
Re: [PATCH V2 1/2] Input: of_keymap: Introduce matrix_keypad_of_build_keymap()
On 03/27/2012 10:55 PM, Viresh Kumar wrote: > On 3/27/2012 9:15 PM, Stephen Warren wrote: static int __devinit tegra_kbc_probe(struct platform_device *pdev) >> ... + if (pdev->dev.of_node) { + /* FIXME: Add handling of linux,fn-keymap here */ + err = matrix_keypad_of_build_keymap(&pdev->dev, KBC_ROW_SHIFT, + input_dev->keycode, input_dev->keybit, + "linux,keymap"); >> >> Where do input_dev->keycode/keybit get allocated? As far as I can tell, >> matrix_keypad_of_build_keymap() just writes to those and assumes they're >> already allocated. > > If i am not reading the code incorrectly, keycode is allocated memory with > kbc. And then we do this: > > input_dev->keycode = kbc->keycode; > > keybit is again present as part of struct input_dev. > Am i missing something. Ah right, I'd been looking inside input_allocate_device() rather than the specific driver's probe(). So, no issue here. diff --git a/drivers/input/of_keymap.c b/drivers/input/of_keymap.c >> ... +int matrix_keypad_of_build_keymap(struct device *dev, unsigned int row_shift, >> ... + keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code; + __set_bit(code, keybit); >> How bit are keymap and keybit? > > Couldn't get this one. :( > Can you please elaborate the question a bit? s/bit/big/ might make the question clearer:-) >> I think we need range-checking here to >> make sure that row/col/row_shift/code are valid and in-range. > > I picked this directly from matrix_keypad_build_keymap() as is. > Anyway there is no loss in improving it. :) > > What kind of range-check you are looking for? > Currently we do following > > unsigned int row = KEY_ROW(key); > unsigned int col = KEY_COL(key); > unsigned short code = KEY_VAL(key); > > All these macros '&' 'key' with 0xFF, 0xFF and 0x. > Which is also kind of range checking. The size of the keycode array is much smaller though: mach-tegra's kbc.h: #define KBC_MAX_ROW 16 #define KBC_MAX_COL 8 #define KBC_MAX_KEY (KBC_MAX_ROW * KBC_MAX_COL) tegra-kbc.c: struct tegra_kbc { ... unsigned short keycode[KBC_MAX_KEY * 2]; so the DT parsing can easily overflow this, and is driven by user-supplied data. I think you'll need to pass input_dev->keycodesize into matrix_keypad_of_build_keymap() to achieve the overall range-checking, but also checking col against (1
Re: [PATCH V2 1/2] Input: of_keymap: Introduce matrix_keypad_of_build_keymap()
On 3/27/2012 9:15 PM, Stephen Warren wrote: >> > static int __devinit tegra_kbc_probe(struct platform_device *pdev) > ... >> > + if (pdev->dev.of_node) { >> > + /* FIXME: Add handling of linux,fn-keymap here */ >> > + err = matrix_keypad_of_build_keymap(&pdev->dev, KBC_ROW_SHIFT, >> > + input_dev->keycode, input_dev->keybit, >> > + "linux,keymap"); > Where do input_dev->keycode/keybit get allocated? As far as I can tell, > matrix_keypad_of_build_keymap() just writes to those and assumes they're > already allocated. If i am not reading the code incorrectly, keycode is allocated memory with kbc. And then we do this: input_dev->keycode = kbc->keycode; keybit is again present as part of struct input_dev. Am i missing something. >> > diff --git a/drivers/input/of_keymap.c b/drivers/input/of_keymap.c > ... >> > +int matrix_keypad_of_build_keymap(struct device *dev, unsigned int >> > row_shift, > ... >> > + keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code; >> > + __set_bit(code, keybit); > How bit are keymap and keybit? Couldn't get this one. :( Can you please elaborate the question a bit? > I think we need range-checking here to > make sure that row/col/row_shift/code are valid and in-range. I picked this directly from matrix_keypad_build_keymap() as is. Anyway there is no loss in improving it. :) What kind of range-check you are looking for? Currently we do following unsigned int row = KEY_ROW(key); unsigned int col = KEY_COL(key); unsigned short code = KEY_VAL(key); All these macros '&' 'key' with 0xFF, 0xFF and 0x. Which is also kind of range checking. -- viresh ___ devicetree-discuss mailing list devicetree-discuss@lists.ozlabs.org https://lists.ozlabs.org/listinfo/devicetree-discuss
Re: [PATCH V2 1/2] Input: of_keymap: Introduce matrix_keypad_of_build_keymap()
On 03/26/2012 11:38 PM, Viresh Kumar wrote: > We don't need to allocate memory for keymap in > matrix_keyboard_of_fill_keymap(), > as this would only be used by matrix_keyboard_of_free_keymap(). Instead create > another routine matrix_keypad_of_build_keymap() which reads directly the > property from struct device_node and builds keymap. > > With this eariler routines matrix_keyboard_of_fill_keymap() and > matrix_keyboard_of_free_keymap() go away. > > This patch also fixes tegra driver according to these changes. > diff --git a/drivers/input/keyboard/tegra-kbc.c > b/drivers/input/keyboard/tegra-kbc.c ... > static int __devinit tegra_kbc_probe(struct platform_device *pdev) ... > + if (pdev->dev.of_node) { > + /* FIXME: Add handling of linux,fn-keymap here */ > + err = matrix_keypad_of_build_keymap(&pdev->dev, KBC_ROW_SHIFT, > + input_dev->keycode, input_dev->keybit, > + "linux,keymap"); Where do input_dev->keycode/keybit get allocated? As far as I can tell, matrix_keypad_of_build_keymap() just writes to those and assumes they're already allocated. > diff --git a/drivers/input/of_keymap.c b/drivers/input/of_keymap.c ... > +int matrix_keypad_of_build_keymap(struct device *dev, unsigned int row_shift, ... > + keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code; > + __set_bit(code, keybit); How bit are keymap and keybit? I think we need range-checking here to make sure that row/col/row_shift/code are valid and in-range. ___ devicetree-discuss mailing list devicetree-discuss@lists.ozlabs.org https://lists.ozlabs.org/listinfo/devicetree-discuss
[PATCH V2 1/2] Input: of_keymap: Introduce matrix_keypad_of_build_keymap()
We don't need to allocate memory for keymap in matrix_keyboard_of_fill_keymap(), as this would only be used by matrix_keyboard_of_free_keymap(). Instead create another routine matrix_keypad_of_build_keymap() which reads directly the property from struct device_node and builds keymap. With this eariler routines matrix_keyboard_of_fill_keymap() and matrix_keyboard_of_free_keymap() go away. This patch also fixes tegra driver according to these changes. Signed-off-by: Viresh Kumar --- V2: - Introduced matrix_keypad_of_build_keymap() and removed fill and free keymap routines. - Updated tegra-kbc. drivers/input/keyboard/tegra-kbc.c | 33 -- drivers/input/of_keymap.c | 82 +-- include/linux/input/matrix_keypad.h | 18 +++- 3 files changed, 66 insertions(+), 67 deletions(-) diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 21c42f8..96ee31e 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -659,10 +659,6 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev) pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL; } - pdata->keymap_data = matrix_keyboard_of_fill_keymap(np, "linux,keymap"); - - /* FIXME: Add handling of linux,fn-keymap here */ - return pdata; } #else @@ -676,7 +672,6 @@ static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( static int __devinit tegra_kbc_probe(struct platform_device *pdev) { const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data; - const struct matrix_keymap_data *keymap_data; struct tegra_kbc *kbc; struct input_dev *input_dev; struct resource *res; @@ -775,9 +770,24 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) kbc->use_fn_map = pdata->use_fn_map; kbc->use_ghost_filter = pdata->use_ghost_filter; - keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; - matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, - input_dev->keycode, input_dev->keybit); + + if (pdev->dev.of_node) { + /* FIXME: Add handling of linux,fn-keymap here */ + err = matrix_keypad_of_build_keymap(&pdev->dev, KBC_ROW_SHIFT, + input_dev->keycode, input_dev->keybit, + "linux,keymap"); + if (err) { + dev_err(&pdev->dev, "OF: failed to build keymap\n"); + goto err_put_clk; + } + } else { + const struct matrix_keymap_data *keymap_data = + pdata->keymap_data ?: &tegra_kbc_default_keymap_data; + + matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, + input_dev->keycode, input_dev->keybit); + } + kbc->wakeup_key = pdata->wakeup_key; err = request_irq(kbc->irq, tegra_kbc_isr, @@ -798,9 +808,6 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, kbc); device_init_wakeup(&pdev->dev, pdata->wakeup); - if (!pdev->dev.platform_data) - matrix_keyboard_of_free_keymap(pdata->keymap_data); - return 0; err_free_irq: @@ -815,10 +822,8 @@ err_free_mem: input_free_device(input_dev); kfree(kbc); err_free_pdata: - if (!pdev->dev.platform_data) { - matrix_keyboard_of_free_keymap(pdata->keymap_data); + if (!pdev->dev.platform_data) kfree(pdata); - } return err; } diff --git a/drivers/input/of_keymap.c b/drivers/input/of_keymap.c index 061493d..2837566 100644 --- a/drivers/input/of_keymap.c +++ b/drivers/input/of_keymap.c @@ -17,6 +17,7 @@ * */ +#include #include #include #include @@ -26,62 +27,61 @@ #include #include -struct matrix_keymap_data * -matrix_keyboard_of_fill_keymap(struct device_node *np, - const char *propname) +/** + * matrix_keypad_of_build_keymap - convert platform DT keymap into matrix keymap + * @dev: Pointer to struct device, will be used for getting struct device_node + * @row_shift: number of bits to shift row value by to advance to the next + * line in the keymap + * @keymap: expanded version of keymap that is suitable for use by + * matrix keyboad driver + * @keybit: pointer to bitmap of keys supported by input device + * @propname: Device Tree property name to be used for reading keymap. If passed + * as NULL, "linux,keymap" is used. + * + * This function creates an array of keycodes, by reading propname property from + * device tree passed, that is suitable for using in a standard matrix keyboard + * driver that uses row and col as indices. + */ +int matrix_keypad_of_build_keymap(struct device *dev, unsigned int row_shift, + unsigned short