touchscreen.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Generic helper functions for touchscreens and other two-dimensional
  4. * pointing devices
  5. *
  6. * Copyright (c) 2014 Sebastian Reichel <[email protected]>
  7. */
  8. #include <linux/property.h>
  9. #include <linux/input.h>
  10. #include <linux/input/mt.h>
  11. #include <linux/input/touchscreen.h>
  12. #include <linux/module.h>
  13. static bool touchscreen_get_prop_u32(struct device *dev,
  14. const char *property,
  15. unsigned int default_value,
  16. unsigned int *value)
  17. {
  18. u32 val;
  19. int error;
  20. error = device_property_read_u32(dev, property, &val);
  21. if (error) {
  22. *value = default_value;
  23. return false;
  24. }
  25. *value = val;
  26. return true;
  27. }
  28. static void touchscreen_set_params(struct input_dev *dev,
  29. unsigned long axis,
  30. int min, int max, int fuzz)
  31. {
  32. struct input_absinfo *absinfo;
  33. if (!test_bit(axis, dev->absbit)) {
  34. dev_warn(&dev->dev,
  35. "Parameters are specified but the axis %lu is not set up\n",
  36. axis);
  37. return;
  38. }
  39. absinfo = &dev->absinfo[axis];
  40. absinfo->minimum = min;
  41. absinfo->maximum = max;
  42. absinfo->fuzz = fuzz;
  43. }
  44. /**
  45. * touchscreen_parse_properties - parse common touchscreen properties
  46. * @input: input device that should be parsed
  47. * @multitouch: specifies whether parsed properties should be applied to
  48. * single-touch or multi-touch axes
  49. * @prop: pointer to a struct touchscreen_properties into which to store
  50. * axis swap and invert info for use with touchscreen_report_x_y();
  51. * or %NULL
  52. *
  53. * This function parses common properties for touchscreens and sets up the
  54. * input device accordingly. The function keeps previously set up default
  55. * values if no value is specified.
  56. */
  57. void touchscreen_parse_properties(struct input_dev *input, bool multitouch,
  58. struct touchscreen_properties *prop)
  59. {
  60. struct device *dev = input->dev.parent;
  61. struct input_absinfo *absinfo;
  62. unsigned int axis, axis_x, axis_y;
  63. unsigned int minimum, maximum, fuzz;
  64. bool data_present;
  65. input_alloc_absinfo(input);
  66. if (!input->absinfo)
  67. return;
  68. axis_x = multitouch ? ABS_MT_POSITION_X : ABS_X;
  69. axis_y = multitouch ? ABS_MT_POSITION_Y : ABS_Y;
  70. data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-x",
  71. input_abs_get_min(input, axis_x),
  72. &minimum);
  73. data_present |= touchscreen_get_prop_u32(dev, "touchscreen-size-x",
  74. input_abs_get_max(input,
  75. axis_x) + 1,
  76. &maximum);
  77. data_present |= touchscreen_get_prop_u32(dev, "touchscreen-fuzz-x",
  78. input_abs_get_fuzz(input, axis_x),
  79. &fuzz);
  80. if (data_present)
  81. touchscreen_set_params(input, axis_x, minimum, maximum - 1, fuzz);
  82. data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-y",
  83. input_abs_get_min(input, axis_y),
  84. &minimum);
  85. data_present |= touchscreen_get_prop_u32(dev, "touchscreen-size-y",
  86. input_abs_get_max(input,
  87. axis_y) + 1,
  88. &maximum);
  89. data_present |= touchscreen_get_prop_u32(dev, "touchscreen-fuzz-y",
  90. input_abs_get_fuzz(input, axis_y),
  91. &fuzz);
  92. if (data_present)
  93. touchscreen_set_params(input, axis_y, minimum, maximum - 1, fuzz);
  94. axis = multitouch ? ABS_MT_PRESSURE : ABS_PRESSURE;
  95. data_present = touchscreen_get_prop_u32(dev,
  96. "touchscreen-max-pressure",
  97. input_abs_get_max(input, axis),
  98. &maximum);
  99. data_present |= touchscreen_get_prop_u32(dev,
  100. "touchscreen-fuzz-pressure",
  101. input_abs_get_fuzz(input, axis),
  102. &fuzz);
  103. if (data_present)
  104. touchscreen_set_params(input, axis, 0, maximum, fuzz);
  105. if (!prop)
  106. return;
  107. prop->max_x = input_abs_get_max(input, axis_x);
  108. prop->max_y = input_abs_get_max(input, axis_y);
  109. prop->invert_x =
  110. device_property_read_bool(dev, "touchscreen-inverted-x");
  111. if (prop->invert_x) {
  112. absinfo = &input->absinfo[axis_x];
  113. absinfo->maximum -= absinfo->minimum;
  114. absinfo->minimum = 0;
  115. }
  116. prop->invert_y =
  117. device_property_read_bool(dev, "touchscreen-inverted-y");
  118. if (prop->invert_y) {
  119. absinfo = &input->absinfo[axis_y];
  120. absinfo->maximum -= absinfo->minimum;
  121. absinfo->minimum = 0;
  122. }
  123. prop->swap_x_y =
  124. device_property_read_bool(dev, "touchscreen-swapped-x-y");
  125. if (prop->swap_x_y)
  126. swap(input->absinfo[axis_x], input->absinfo[axis_y]);
  127. }
  128. EXPORT_SYMBOL(touchscreen_parse_properties);
  129. static void
  130. touchscreen_apply_prop_to_x_y(const struct touchscreen_properties *prop,
  131. unsigned int *x, unsigned int *y)
  132. {
  133. if (prop->invert_x)
  134. *x = prop->max_x - *x;
  135. if (prop->invert_y)
  136. *y = prop->max_y - *y;
  137. if (prop->swap_x_y)
  138. swap(*x, *y);
  139. }
  140. /**
  141. * touchscreen_set_mt_pos - Set input_mt_pos coordinates
  142. * @pos: input_mt_pos to set coordinates of
  143. * @prop: pointer to a struct touchscreen_properties
  144. * @x: X coordinate to store in pos
  145. * @y: Y coordinate to store in pos
  146. *
  147. * Adjust the passed in x and y values applying any axis inversion and
  148. * swapping requested in the passed in touchscreen_properties and store
  149. * the result in a struct input_mt_pos.
  150. */
  151. void touchscreen_set_mt_pos(struct input_mt_pos *pos,
  152. const struct touchscreen_properties *prop,
  153. unsigned int x, unsigned int y)
  154. {
  155. touchscreen_apply_prop_to_x_y(prop, &x, &y);
  156. pos->x = x;
  157. pos->y = y;
  158. }
  159. EXPORT_SYMBOL(touchscreen_set_mt_pos);
  160. /**
  161. * touchscreen_report_pos - Report touchscreen coordinates
  162. * @input: input_device to report coordinates for
  163. * @prop: pointer to a struct touchscreen_properties
  164. * @x: X coordinate to report
  165. * @y: Y coordinate to report
  166. * @multitouch: Report coordinates on single-touch or multi-touch axes
  167. *
  168. * Adjust the passed in x and y values applying any axis inversion and
  169. * swapping requested in the passed in touchscreen_properties and then
  170. * report the resulting coordinates on the input_dev's x and y axis.
  171. */
  172. void touchscreen_report_pos(struct input_dev *input,
  173. const struct touchscreen_properties *prop,
  174. unsigned int x, unsigned int y,
  175. bool multitouch)
  176. {
  177. touchscreen_apply_prop_to_x_y(prop, &x, &y);
  178. input_report_abs(input, multitouch ? ABS_MT_POSITION_X : ABS_X, x);
  179. input_report_abs(input, multitouch ? ABS_MT_POSITION_Y : ABS_Y, y);
  180. }
  181. EXPORT_SYMBOL(touchscreen_report_pos);
  182. MODULE_LICENSE("GPL v2");
  183. MODULE_DESCRIPTION("Helper functions for touchscreens and other devices");