0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/property.h>
0010 #include <linux/input.h>
0011 #include <linux/input/mt.h>
0012 #include <linux/input/touchscreen.h>
0013 #include <linux/module.h>
0014
0015 static bool touchscreen_get_prop_u32(struct device *dev,
0016 const char *property,
0017 unsigned int default_value,
0018 unsigned int *value)
0019 {
0020 u32 val;
0021 int error;
0022
0023 error = device_property_read_u32(dev, property, &val);
0024 if (error) {
0025 *value = default_value;
0026 return false;
0027 }
0028
0029 *value = val;
0030 return true;
0031 }
0032
0033 static void touchscreen_set_params(struct input_dev *dev,
0034 unsigned long axis,
0035 int min, int max, int fuzz)
0036 {
0037 struct input_absinfo *absinfo;
0038
0039 if (!test_bit(axis, dev->absbit)) {
0040 dev_warn(&dev->dev,
0041 "Parameters are specified but the axis %lu is not set up\n",
0042 axis);
0043 return;
0044 }
0045
0046 absinfo = &dev->absinfo[axis];
0047 absinfo->minimum = min;
0048 absinfo->maximum = max;
0049 absinfo->fuzz = fuzz;
0050 }
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 void touchscreen_parse_properties(struct input_dev *input, bool multitouch,
0066 struct touchscreen_properties *prop)
0067 {
0068 struct device *dev = input->dev.parent;
0069 struct input_absinfo *absinfo;
0070 unsigned int axis, axis_x, axis_y;
0071 unsigned int minimum, maximum, fuzz;
0072 bool data_present;
0073
0074 input_alloc_absinfo(input);
0075 if (!input->absinfo)
0076 return;
0077
0078 axis_x = multitouch ? ABS_MT_POSITION_X : ABS_X;
0079 axis_y = multitouch ? ABS_MT_POSITION_Y : ABS_Y;
0080
0081 data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-x",
0082 input_abs_get_min(input, axis_x),
0083 &minimum);
0084 data_present |= touchscreen_get_prop_u32(dev, "touchscreen-size-x",
0085 input_abs_get_max(input,
0086 axis_x) + 1,
0087 &maximum);
0088 data_present |= touchscreen_get_prop_u32(dev, "touchscreen-fuzz-x",
0089 input_abs_get_fuzz(input, axis_x),
0090 &fuzz);
0091 if (data_present)
0092 touchscreen_set_params(input, axis_x, minimum, maximum - 1, fuzz);
0093
0094 data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-y",
0095 input_abs_get_min(input, axis_y),
0096 &minimum);
0097 data_present |= touchscreen_get_prop_u32(dev, "touchscreen-size-y",
0098 input_abs_get_max(input,
0099 axis_y) + 1,
0100 &maximum);
0101 data_present |= touchscreen_get_prop_u32(dev, "touchscreen-fuzz-y",
0102 input_abs_get_fuzz(input, axis_y),
0103 &fuzz);
0104 if (data_present)
0105 touchscreen_set_params(input, axis_y, minimum, maximum - 1, fuzz);
0106
0107 axis = multitouch ? ABS_MT_PRESSURE : ABS_PRESSURE;
0108 data_present = touchscreen_get_prop_u32(dev,
0109 "touchscreen-max-pressure",
0110 input_abs_get_max(input, axis),
0111 &maximum);
0112 data_present |= touchscreen_get_prop_u32(dev,
0113 "touchscreen-fuzz-pressure",
0114 input_abs_get_fuzz(input, axis),
0115 &fuzz);
0116 if (data_present)
0117 touchscreen_set_params(input, axis, 0, maximum, fuzz);
0118
0119 if (!prop)
0120 return;
0121
0122 prop->max_x = input_abs_get_max(input, axis_x);
0123 prop->max_y = input_abs_get_max(input, axis_y);
0124
0125 prop->invert_x =
0126 device_property_read_bool(dev, "touchscreen-inverted-x");
0127 if (prop->invert_x) {
0128 absinfo = &input->absinfo[axis_x];
0129 absinfo->maximum -= absinfo->minimum;
0130 absinfo->minimum = 0;
0131 }
0132
0133 prop->invert_y =
0134 device_property_read_bool(dev, "touchscreen-inverted-y");
0135 if (prop->invert_y) {
0136 absinfo = &input->absinfo[axis_y];
0137 absinfo->maximum -= absinfo->minimum;
0138 absinfo->minimum = 0;
0139 }
0140
0141 prop->swap_x_y =
0142 device_property_read_bool(dev, "touchscreen-swapped-x-y");
0143 if (prop->swap_x_y)
0144 swap(input->absinfo[axis_x], input->absinfo[axis_y]);
0145 }
0146 EXPORT_SYMBOL(touchscreen_parse_properties);
0147
0148 static void
0149 touchscreen_apply_prop_to_x_y(const struct touchscreen_properties *prop,
0150 unsigned int *x, unsigned int *y)
0151 {
0152 if (prop->invert_x)
0153 *x = prop->max_x - *x;
0154
0155 if (prop->invert_y)
0156 *y = prop->max_y - *y;
0157
0158 if (prop->swap_x_y)
0159 swap(*x, *y);
0160 }
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 void touchscreen_set_mt_pos(struct input_mt_pos *pos,
0174 const struct touchscreen_properties *prop,
0175 unsigned int x, unsigned int y)
0176 {
0177 touchscreen_apply_prop_to_x_y(prop, &x, &y);
0178 pos->x = x;
0179 pos->y = y;
0180 }
0181 EXPORT_SYMBOL(touchscreen_set_mt_pos);
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195 void touchscreen_report_pos(struct input_dev *input,
0196 const struct touchscreen_properties *prop,
0197 unsigned int x, unsigned int y,
0198 bool multitouch)
0199 {
0200 touchscreen_apply_prop_to_x_y(prop, &x, &y);
0201 input_report_abs(input, multitouch ? ABS_MT_POSITION_X : ABS_X, x);
0202 input_report_abs(input, multitouch ? ABS_MT_POSITION_Y : ABS_Y, y);
0203 }
0204 EXPORT_SYMBOL(touchscreen_report_pos);
0205
0206 MODULE_LICENSE("GPL v2");
0207 MODULE_DESCRIPTION("Helper functions for touchscreens and other devices");