diff options
author | Alexandre Pereira da Silva <aletes.xgr@gmail.com> | 2012-07-30 01:18:47 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-08-22 01:28:26 -0400 |
commit | 219edc71784ff8a3537ffbe64baded61ce4048b9 (patch) | |
tree | a0ced5c45e239201e8f4af99eaab0156606f8bd3 /drivers/input | |
parent | c0394506e69b37c47d391c2a7bbea3ea236d8ec8 (diff) |
Input: gpio_keys - clean up device tree parser
- fix sizeof in memset;
- clean up dt properties extraction;
- use for_each_chil_of_node macro;
- use of_get_child_count();
- use of_match_ptr macro.
Signed-off-by: Alexandre Pereira da Silva <aletes.xgr@gmail.com>
Acked-by: Rob Herring <rob.herring@calxeda.com>
[Fabio Estevam <fabio.estevam@freescale.com>: fix fix NULL pointer
dereference for dt case - pdata->buttons wasn't initialized]
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 161 |
1 files changed, 80 insertions, 81 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index cbb1add43d5e..b890231debd8 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -43,11 +43,9 @@ struct gpio_button_data { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct gpio_keys_drvdata { | 45 | struct gpio_keys_drvdata { |
46 | const struct gpio_keys_platform_data *pdata; | ||
46 | struct input_dev *input; | 47 | struct input_dev *input; |
47 | struct mutex disable_lock; | 48 | struct mutex disable_lock; |
48 | unsigned int n_buttons; | ||
49 | int (*enable)(struct device *dev); | ||
50 | void (*disable)(struct device *dev); | ||
51 | struct gpio_button_data data[0]; | 49 | struct gpio_button_data data[0]; |
52 | }; | 50 | }; |
53 | 51 | ||
@@ -171,7 +169,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, | |||
171 | if (!bits) | 169 | if (!bits) |
172 | return -ENOMEM; | 170 | return -ENOMEM; |
173 | 171 | ||
174 | for (i = 0; i < ddata->n_buttons; i++) { | 172 | for (i = 0; i < ddata->pdata->nbuttons; i++) { |
175 | struct gpio_button_data *bdata = &ddata->data[i]; | 173 | struct gpio_button_data *bdata = &ddata->data[i]; |
176 | 174 | ||
177 | if (bdata->button->type != type) | 175 | if (bdata->button->type != type) |
@@ -219,7 +217,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, | |||
219 | goto out; | 217 | goto out; |
220 | 218 | ||
221 | /* First validate */ | 219 | /* First validate */ |
222 | for (i = 0; i < ddata->n_buttons; i++) { | 220 | for (i = 0; i < ddata->pdata->nbuttons; i++) { |
223 | struct gpio_button_data *bdata = &ddata->data[i]; | 221 | struct gpio_button_data *bdata = &ddata->data[i]; |
224 | 222 | ||
225 | if (bdata->button->type != type) | 223 | if (bdata->button->type != type) |
@@ -234,7 +232,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, | |||
234 | 232 | ||
235 | mutex_lock(&ddata->disable_lock); | 233 | mutex_lock(&ddata->disable_lock); |
236 | 234 | ||
237 | for (i = 0; i < ddata->n_buttons; i++) { | 235 | for (i = 0; i < ddata->pdata->nbuttons; i++) { |
238 | struct gpio_button_data *bdata = &ddata->data[i]; | 236 | struct gpio_button_data *bdata = &ddata->data[i]; |
239 | 237 | ||
240 | if (bdata->button->type != type) | 238 | if (bdata->button->type != type) |
@@ -523,56 +521,64 @@ fail: | |||
523 | static int gpio_keys_open(struct input_dev *input) | 521 | static int gpio_keys_open(struct input_dev *input) |
524 | { | 522 | { |
525 | struct gpio_keys_drvdata *ddata = input_get_drvdata(input); | 523 | struct gpio_keys_drvdata *ddata = input_get_drvdata(input); |
524 | const struct gpio_keys_platform_data *pdata = ddata->pdata; | ||
526 | 525 | ||
527 | return ddata->enable ? ddata->enable(input->dev.parent) : 0; | 526 | return pdata->enable ? pdata->enable(input->dev.parent) : 0; |
528 | } | 527 | } |
529 | 528 | ||
530 | static void gpio_keys_close(struct input_dev *input) | 529 | static void gpio_keys_close(struct input_dev *input) |
531 | { | 530 | { |
532 | struct gpio_keys_drvdata *ddata = input_get_drvdata(input); | 531 | struct gpio_keys_drvdata *ddata = input_get_drvdata(input); |
532 | const struct gpio_keys_platform_data *pdata = ddata->pdata; | ||
533 | 533 | ||
534 | if (ddata->disable) | 534 | if (pdata->disable) |
535 | ddata->disable(input->dev.parent); | 535 | pdata->disable(input->dev.parent); |
536 | } | 536 | } |
537 | 537 | ||
538 | /* | 538 | /* |
539 | * Handlers for alternative sources of platform_data | 539 | * Handlers for alternative sources of platform_data |
540 | */ | 540 | */ |
541 | |||
541 | #ifdef CONFIG_OF | 542 | #ifdef CONFIG_OF |
542 | /* | 543 | /* |
543 | * Translate OpenFirmware node properties into platform_data | 544 | * Translate OpenFirmware node properties into platform_data |
544 | */ | 545 | */ |
545 | static int gpio_keys_get_devtree_pdata(struct device *dev, | 546 | static struct gpio_keys_platform_data * __devinit |
546 | struct gpio_keys_platform_data *pdata) | 547 | gpio_keys_get_devtree_pdata(struct device *dev) |
547 | { | 548 | { |
548 | struct device_node *node, *pp; | 549 | struct device_node *node, *pp; |
550 | struct gpio_keys_platform_data *pdata; | ||
551 | struct gpio_keys_button *button; | ||
552 | int error; | ||
553 | int nbuttons; | ||
549 | int i; | 554 | int i; |
550 | struct gpio_keys_button *buttons; | ||
551 | u32 reg; | ||
552 | 555 | ||
553 | node = dev->of_node; | 556 | node = dev->of_node; |
554 | if (node == NULL) | 557 | if (!node) { |
555 | return -ENODEV; | 558 | error = -ENODEV; |
556 | 559 | goto err_out; | |
557 | memset(pdata, 0, sizeof *pdata); | 560 | } |
558 | 561 | ||
559 | pdata->rep = !!of_get_property(node, "autorepeat", NULL); | 562 | nbuttons = of_get_child_count(node); |
563 | if (nbuttons == 0) { | ||
564 | error = -ENODEV; | ||
565 | goto err_out; | ||
566 | } | ||
560 | 567 | ||
561 | /* First count the subnodes */ | 568 | pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button), |
562 | pp = NULL; | 569 | GFP_KERNEL); |
563 | while ((pp = of_get_next_child(node, pp))) | 570 | if (!pdata) { |
564 | pdata->nbuttons++; | 571 | error = -ENOMEM; |
572 | goto err_out; | ||
573 | } | ||
565 | 574 | ||
566 | if (pdata->nbuttons == 0) | 575 | pdata->buttons = (struct gpio_keys_button *)(pdata + 1); |
567 | return -ENODEV; | 576 | pdata->nbuttons = nbuttons; |
568 | 577 | ||
569 | buttons = kzalloc(pdata->nbuttons * (sizeof *buttons), GFP_KERNEL); | 578 | pdata->rep = !!of_get_property(node, "autorepeat", NULL); |
570 | if (!buttons) | ||
571 | return -ENOMEM; | ||
572 | 579 | ||
573 | pp = NULL; | ||
574 | i = 0; | 580 | i = 0; |
575 | while ((pp = of_get_next_child(node, pp))) { | 581 | for_each_child_of_node(node, pp) { |
576 | enum of_gpio_flags flags; | 582 | enum of_gpio_flags flags; |
577 | 583 | ||
578 | if (!of_find_property(pp, "gpios", NULL)) { | 584 | if (!of_find_property(pp, "gpios", NULL)) { |
@@ -580,39 +586,42 @@ static int gpio_keys_get_devtree_pdata(struct device *dev, | |||
580 | dev_warn(dev, "Found button without gpios\n"); | 586 | dev_warn(dev, "Found button without gpios\n"); |
581 | continue; | 587 | continue; |
582 | } | 588 | } |
583 | buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags); | ||
584 | buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
585 | 589 | ||
586 | if (of_property_read_u32(pp, "linux,code", ®)) { | 590 | button = &pdata->buttons[i++]; |
587 | dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio); | ||
588 | goto out_fail; | ||
589 | } | ||
590 | buttons[i].code = reg; | ||
591 | 591 | ||
592 | buttons[i].desc = of_get_property(pp, "label", NULL); | 592 | button->gpio = of_get_gpio_flags(pp, 0, &flags); |
593 | button->active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
593 | 594 | ||
594 | if (of_property_read_u32(pp, "linux,input-type", ®) == 0) | 595 | if (of_property_read_u32(pp, "linux,code", &button->code)) { |
595 | buttons[i].type = reg; | 596 | dev_err(dev, "Button without keycode: 0x%x\n", |
596 | else | 597 | button->gpio); |
597 | buttons[i].type = EV_KEY; | 598 | error = -EINVAL; |
599 | goto err_free_pdata; | ||
600 | } | ||
598 | 601 | ||
599 | buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); | 602 | button->desc = of_get_property(pp, "label", NULL); |
600 | 603 | ||
601 | if (of_property_read_u32(pp, "debounce-interval", ®) == 0) | 604 | if (of_property_read_u32(pp, "linux,input-type", &button->type)) |
602 | buttons[i].debounce_interval = reg; | 605 | button->type = EV_KEY; |
603 | else | 606 | |
604 | buttons[i].debounce_interval = 5; | 607 | button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); |
605 | 608 | ||
606 | i++; | 609 | if (of_property_read_u32(pp, "debounce-interval", |
610 | &button->debounce_interval)) | ||
611 | button->debounce_interval = 5; | ||
607 | } | 612 | } |
608 | 613 | ||
609 | pdata->buttons = buttons; | 614 | if (pdata->nbuttons == 0) { |
615 | error = -EINVAL; | ||
616 | goto err_free_pdata; | ||
617 | } | ||
610 | 618 | ||
611 | return 0; | 619 | return pdata; |
612 | 620 | ||
613 | out_fail: | 621 | err_free_pdata: |
614 | kfree(buttons); | 622 | kfree(pdata); |
615 | return -ENODEV; | 623 | err_out: |
624 | return ERR_PTR(error); | ||
616 | } | 625 | } |
617 | 626 | ||
618 | static struct of_device_id gpio_keys_of_match[] = { | 627 | static struct of_device_id gpio_keys_of_match[] = { |
@@ -623,14 +632,12 @@ MODULE_DEVICE_TABLE(of, gpio_keys_of_match); | |||
623 | 632 | ||
624 | #else | 633 | #else |
625 | 634 | ||
626 | static int gpio_keys_get_devtree_pdata(struct device *dev, | 635 | static inline struct gpio_keys_platform_data * |
627 | struct gpio_keys_platform_data *altp) | 636 | gpio_keys_get_devtree_pdata(struct device *dev) |
628 | { | 637 | { |
629 | return -ENODEV; | 638 | return ERR_PTR(-ENODEV); |
630 | } | 639 | } |
631 | 640 | ||
632 | #define gpio_keys_of_match NULL | ||
633 | |||
634 | #endif | 641 | #endif |
635 | 642 | ||
636 | static void gpio_remove_key(struct gpio_button_data *bdata) | 643 | static void gpio_remove_key(struct gpio_button_data *bdata) |
@@ -645,19 +652,17 @@ static void gpio_remove_key(struct gpio_button_data *bdata) | |||
645 | 652 | ||
646 | static int __devinit gpio_keys_probe(struct platform_device *pdev) | 653 | static int __devinit gpio_keys_probe(struct platform_device *pdev) |
647 | { | 654 | { |
648 | const struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
649 | struct gpio_keys_drvdata *ddata; | ||
650 | struct device *dev = &pdev->dev; | 655 | struct device *dev = &pdev->dev; |
651 | struct gpio_keys_platform_data alt_pdata; | 656 | const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); |
657 | struct gpio_keys_drvdata *ddata; | ||
652 | struct input_dev *input; | 658 | struct input_dev *input; |
653 | int i, error; | 659 | int i, error; |
654 | int wakeup = 0; | 660 | int wakeup = 0; |
655 | 661 | ||
656 | if (!pdata) { | 662 | if (!pdata) { |
657 | error = gpio_keys_get_devtree_pdata(dev, &alt_pdata); | 663 | pdata = gpio_keys_get_devtree_pdata(dev); |
658 | if (error) | 664 | if (IS_ERR(pdata)) |
659 | return error; | 665 | return PTR_ERR(pdata); |
660 | pdata = &alt_pdata; | ||
661 | } | 666 | } |
662 | 667 | ||
663 | ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + | 668 | ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + |
@@ -670,10 +675,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
670 | goto fail1; | 675 | goto fail1; |
671 | } | 676 | } |
672 | 677 | ||
678 | ddata->pdata = pdata; | ||
673 | ddata->input = input; | 679 | ddata->input = input; |
674 | ddata->n_buttons = pdata->nbuttons; | ||
675 | ddata->enable = pdata->enable; | ||
676 | ddata->disable = pdata->disable; | ||
677 | mutex_init(&ddata->disable_lock); | 680 | mutex_init(&ddata->disable_lock); |
678 | 681 | ||
679 | platform_set_drvdata(pdev, ddata); | 682 | platform_set_drvdata(pdev, ddata); |
@@ -742,9 +745,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
742 | fail1: | 745 | fail1: |
743 | input_free_device(input); | 746 | input_free_device(input); |
744 | kfree(ddata); | 747 | kfree(ddata); |
745 | /* If we have no platform_data, we allocated buttons dynamically. */ | 748 | /* If we have no platform data, we allocated pdata dynamically. */ |
746 | if (!pdev->dev.platform_data) | 749 | if (!dev_get_platdata(&pdev->dev)) |
747 | kfree(pdata->buttons); | 750 | kfree(pdata); |
748 | 751 | ||
749 | return error; | 752 | return error; |
750 | } | 753 | } |
@@ -759,18 +762,14 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
759 | 762 | ||
760 | device_init_wakeup(&pdev->dev, 0); | 763 | device_init_wakeup(&pdev->dev, 0); |
761 | 764 | ||
762 | for (i = 0; i < ddata->n_buttons; i++) | 765 | for (i = 0; i < ddata->pdata->nbuttons; i++) |
763 | gpio_remove_key(&ddata->data[i]); | 766 | gpio_remove_key(&ddata->data[i]); |
764 | 767 | ||
765 | input_unregister_device(input); | 768 | input_unregister_device(input); |
766 | 769 | ||
767 | /* | 770 | /* If we have no platform data, we allocated pdata dynamically. */ |
768 | * If we had no platform_data, we allocated buttons dynamically, and | 771 | if (!dev_get_platdata(&pdev->dev)) |
769 | * must free them here. ddata->data[0].button is the pointer to the | 772 | kfree(ddata->pdata); |
770 | * beginning of the allocated array. | ||
771 | */ | ||
772 | if (!pdev->dev.platform_data) | ||
773 | kfree(ddata->data[0].button); | ||
774 | 773 | ||
775 | kfree(ddata); | 774 | kfree(ddata); |
776 | 775 | ||
@@ -784,7 +783,7 @@ static int gpio_keys_suspend(struct device *dev) | |||
784 | int i; | 783 | int i; |
785 | 784 | ||
786 | if (device_may_wakeup(dev)) { | 785 | if (device_may_wakeup(dev)) { |
787 | for (i = 0; i < ddata->n_buttons; i++) { | 786 | for (i = 0; i < ddata->pdata->nbuttons; i++) { |
788 | struct gpio_button_data *bdata = &ddata->data[i]; | 787 | struct gpio_button_data *bdata = &ddata->data[i]; |
789 | if (bdata->button->wakeup) | 788 | if (bdata->button->wakeup) |
790 | enable_irq_wake(bdata->irq); | 789 | enable_irq_wake(bdata->irq); |
@@ -799,7 +798,7 @@ static int gpio_keys_resume(struct device *dev) | |||
799 | struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); | 798 | struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); |
800 | int i; | 799 | int i; |
801 | 800 | ||
802 | for (i = 0; i < ddata->n_buttons; i++) { | 801 | for (i = 0; i < ddata->pdata->nbuttons; i++) { |
803 | struct gpio_button_data *bdata = &ddata->data[i]; | 802 | struct gpio_button_data *bdata = &ddata->data[i]; |
804 | if (bdata->button->wakeup && device_may_wakeup(dev)) | 803 | if (bdata->button->wakeup && device_may_wakeup(dev)) |
805 | disable_irq_wake(bdata->irq); | 804 | disable_irq_wake(bdata->irq); |
@@ -822,7 +821,7 @@ static struct platform_driver gpio_keys_device_driver = { | |||
822 | .name = "gpio-keys", | 821 | .name = "gpio-keys", |
823 | .owner = THIS_MODULE, | 822 | .owner = THIS_MODULE, |
824 | .pm = &gpio_keys_pm_ops, | 823 | .pm = &gpio_keys_pm_ops, |
825 | .of_match_table = gpio_keys_of_match, | 824 | .of_match_table = of_match_ptr(gpio_keys_of_match), |
826 | } | 825 | } |
827 | }; | 826 | }; |
828 | 827 | ||