gpio_tilt_polled.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Driver for tilt switches connected via GPIO lines
  3. * not capable of generating interrupts
  4. *
  5. * Copyright (C) 2011 Heiko Stuebner <heiko@sntech.de>
  6. *
  7. * based on: drivers/input/keyboard/gpio_keys_polled.c
  8. *
  9. * Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org>
  10. * Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com>
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License version 2 as
  14. * published by the Free Software Foundation.
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/slab.h>
  19. #include <linux/input.h>
  20. #include <linux/input-polldev.h>
  21. #include <linux/ioport.h>
  22. #include <linux/platform_device.h>
  23. #include <linux/gpio.h>
  24. #include <linux/input/gpio_tilt.h>
  25. #define DRV_NAME "gpio-tilt-polled"
  26. struct gpio_tilt_polled_dev {
  27. struct input_polled_dev *poll_dev;
  28. struct device *dev;
  29. const struct gpio_tilt_platform_data *pdata;
  30. int last_state;
  31. int threshold;
  32. int count;
  33. };
  34. static void gpio_tilt_polled_poll(struct input_polled_dev *dev)
  35. {
  36. struct gpio_tilt_polled_dev *tdev = dev->private;
  37. const struct gpio_tilt_platform_data *pdata = tdev->pdata;
  38. struct input_dev *input = dev->input;
  39. struct gpio_tilt_state *tilt_state = NULL;
  40. int state, i;
  41. if (tdev->count < tdev->threshold) {
  42. tdev->count++;
  43. } else {
  44. state = 0;
  45. for (i = 0; i < pdata->nr_gpios; i++)
  46. state |= (!!gpio_get_value(pdata->gpios[i].gpio) << i);
  47. if (state != tdev->last_state) {
  48. for (i = 0; i < pdata->nr_states; i++)
  49. if (pdata->states[i].gpios == state)
  50. tilt_state = &pdata->states[i];
  51. if (tilt_state) {
  52. for (i = 0; i < pdata->nr_axes; i++)
  53. input_report_abs(input,
  54. pdata->axes[i].axis,
  55. tilt_state->axes[i]);
  56. input_sync(input);
  57. }
  58. tdev->count = 0;
  59. tdev->last_state = state;
  60. }
  61. }
  62. }
  63. static void gpio_tilt_polled_open(struct input_polled_dev *dev)
  64. {
  65. struct gpio_tilt_polled_dev *tdev = dev->private;
  66. const struct gpio_tilt_platform_data *pdata = tdev->pdata;
  67. if (pdata->enable)
  68. pdata->enable(tdev->dev);
  69. /* report initial state of the axes */
  70. tdev->last_state = -1;
  71. tdev->count = tdev->threshold;
  72. gpio_tilt_polled_poll(tdev->poll_dev);
  73. }
  74. static void gpio_tilt_polled_close(struct input_polled_dev *dev)
  75. {
  76. struct gpio_tilt_polled_dev *tdev = dev->private;
  77. const struct gpio_tilt_platform_data *pdata = tdev->pdata;
  78. if (pdata->disable)
  79. pdata->disable(tdev->dev);
  80. }
  81. static int gpio_tilt_polled_probe(struct platform_device *pdev)
  82. {
  83. const struct gpio_tilt_platform_data *pdata =
  84. dev_get_platdata(&pdev->dev);
  85. struct device *dev = &pdev->dev;
  86. struct gpio_tilt_polled_dev *tdev;
  87. struct input_polled_dev *poll_dev;
  88. struct input_dev *input;
  89. int error, i;
  90. if (!pdata || !pdata->poll_interval)
  91. return -EINVAL;
  92. tdev = kzalloc(sizeof(struct gpio_tilt_polled_dev), GFP_KERNEL);
  93. if (!tdev) {
  94. dev_err(dev, "no memory for private data\n");
  95. return -ENOMEM;
  96. }
  97. error = gpio_request_array(pdata->gpios, pdata->nr_gpios);
  98. if (error) {
  99. dev_err(dev,
  100. "Could not request tilt GPIOs: %d\n", error);
  101. goto err_free_tdev;
  102. }
  103. poll_dev = input_allocate_polled_device();
  104. if (!poll_dev) {
  105. dev_err(dev, "no memory for polled device\n");
  106. error = -ENOMEM;
  107. goto err_free_gpios;
  108. }
  109. poll_dev->private = tdev;
  110. poll_dev->poll = gpio_tilt_polled_poll;
  111. poll_dev->poll_interval = pdata->poll_interval;
  112. poll_dev->open = gpio_tilt_polled_open;
  113. poll_dev->close = gpio_tilt_polled_close;
  114. input = poll_dev->input;
  115. input->name = pdev->name;
  116. input->phys = DRV_NAME"/input0";
  117. input->dev.parent = &pdev->dev;
  118. input->id.bustype = BUS_HOST;
  119. input->id.vendor = 0x0001;
  120. input->id.product = 0x0001;
  121. input->id.version = 0x0100;
  122. __set_bit(EV_ABS, input->evbit);
  123. for (i = 0; i < pdata->nr_axes; i++)
  124. input_set_abs_params(input, pdata->axes[i].axis,
  125. pdata->axes[i].min, pdata->axes[i].max,
  126. pdata->axes[i].fuzz, pdata->axes[i].flat);
  127. tdev->threshold = DIV_ROUND_UP(pdata->debounce_interval,
  128. pdata->poll_interval);
  129. tdev->poll_dev = poll_dev;
  130. tdev->dev = dev;
  131. tdev->pdata = pdata;
  132. error = input_register_polled_device(poll_dev);
  133. if (error) {
  134. dev_err(dev, "unable to register polled device, err=%d\n",
  135. error);
  136. goto err_free_polldev;
  137. }
  138. platform_set_drvdata(pdev, tdev);
  139. return 0;
  140. err_free_polldev:
  141. input_free_polled_device(poll_dev);
  142. err_free_gpios:
  143. gpio_free_array(pdata->gpios, pdata->nr_gpios);
  144. err_free_tdev:
  145. kfree(tdev);
  146. return error;
  147. }
  148. static int gpio_tilt_polled_remove(struct platform_device *pdev)
  149. {
  150. struct gpio_tilt_polled_dev *tdev = platform_get_drvdata(pdev);
  151. const struct gpio_tilt_platform_data *pdata = tdev->pdata;
  152. input_unregister_polled_device(tdev->poll_dev);
  153. input_free_polled_device(tdev->poll_dev);
  154. gpio_free_array(pdata->gpios, pdata->nr_gpios);
  155. kfree(tdev);
  156. return 0;
  157. }
  158. static struct platform_driver gpio_tilt_polled_driver = {
  159. .probe = gpio_tilt_polled_probe,
  160. .remove = gpio_tilt_polled_remove,
  161. .driver = {
  162. .name = DRV_NAME,
  163. },
  164. };
  165. module_platform_driver(gpio_tilt_polled_driver);
  166. MODULE_LICENSE("GPL v2");
  167. MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
  168. MODULE_DESCRIPTION("Polled GPIO tilt driver");
  169. MODULE_ALIAS("platform:" DRV_NAME);