diff options
Diffstat (limited to 'src/caps.c')
| -rw-r--r-- | src/caps.c | 163 |
1 files changed, 129 insertions, 34 deletions
| @@ -26,10 +26,7 @@ | |||
| 26 | * | 26 | * |
| 27 | ****************************************************************************/ | 27 | ****************************************************************************/ |
| 28 | 28 | ||
| 29 | #include "common.h" | 29 | #include "state.h" |
| 30 | |||
| 31 | #define SETABS(c, x, map, key, fd) \ | ||
| 32 | (c->has_##x = getbit(map, key) && getabs(&c->x, key, fd)) | ||
| 33 | 30 | ||
| 34 | static const int SN_COORD = 250; /* coordinate signal-to-noise ratio */ | 31 | static const int SN_COORD = 250; /* coordinate signal-to-noise ratio */ |
| 35 | static const int SN_WIDTH = 100; /* width signal-to-noise ratio */ | 32 | static const int SN_WIDTH = 100; /* width signal-to-noise ratio */ |
| @@ -54,59 +51,157 @@ static int getabs(struct input_absinfo *abs, int key, int fd) | |||
| 54 | return rc >= 0; | 51 | return rc >= 0; |
| 55 | } | 52 | } |
| 56 | 53 | ||
| 57 | static int has_mt_data(const struct mtdev_caps *cap) | 54 | static struct input_absinfo *get_info(struct mtdev *dev, int code) |
| 58 | { | 55 | { |
| 59 | return cap->has_abs[MTDEV_POSITION_X] && cap->has_abs[MTDEV_POSITION_Y]; | 56 | int ix; |
| 57 | |||
| 58 | if (code == ABS_MT_SLOT) | ||
| 59 | return &dev->slot; | ||
| 60 | if (!mtdev_is_absmt(code)) | ||
| 61 | return NULL; | ||
| 62 | |||
| 63 | ix = mtdev_abs2mt(code); | ||
| 64 | if (ix < 11) | ||
| 65 | return &dev->abs[ix]; | ||
| 66 | else | ||
| 67 | return &dev->state->ext_abs[ix - 11]; | ||
| 60 | } | 68 | } |
| 61 | 69 | ||
| 62 | static void default_fuzz(struct mtdev_caps *cap, int bit, int sn) | 70 | static void set_info(struct mtdev *dev, int code, |
| 71 | const unsigned long *bits, int fd) | ||
| 63 | { | 72 | { |
| 64 | if (cap->has_abs[bit] && cap->abs[bit].fuzz == 0) | 73 | int has = getbit(bits, code) && getabs(get_info(dev, code), code, fd); |
| 65 | cap->abs[bit].fuzz = | 74 | mtdev_set_mt_event(dev, code, has); |
| 66 | (cap->abs[bit].maximum - cap->abs[bit].minimum) / sn; | ||
| 67 | } | 75 | } |
| 68 | 76 | ||
| 69 | static int read_caps(struct mtdev_caps *cap, int fd) | 77 | static void default_fuzz(struct mtdev *dev, int code, int sn) |
| 78 | { | ||
| 79 | struct input_absinfo *abs = get_info(dev, code); | ||
| 80 | if (!mtdev_has_mt_event(dev, code) || abs->fuzz) | ||
| 81 | return; | ||
| 82 | abs->fuzz = (abs->maximum - abs->minimum) / sn; | ||
| 83 | } | ||
| 84 | |||
| 85 | int mtdev_configure(struct mtdev *dev, int fd) | ||
| 70 | { | 86 | { |
| 71 | unsigned long absbits[nlongs(ABS_MAX)]; | 87 | unsigned long absbits[nlongs(ABS_MAX)]; |
| 72 | int rc, i; | 88 | int rc, i; |
| 73 | 89 | ||
| 74 | memset(cap, 0, sizeof(struct mtdev_caps)); | ||
| 75 | |||
| 76 | SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits)); | 90 | SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits)); |
| 77 | if (rc < 0) | 91 | if (rc < 0) |
| 78 | return rc; | 92 | return rc; |
| 79 | 93 | ||
| 80 | SETABS(cap, slot, absbits, ABS_MT_SLOT, fd); | 94 | set_info(dev, ABS_MT_SLOT, absbits, fd); |
| 81 | for (i = 0; i < MT_ABS_SIZE; i++) | 95 | for (i = 0; i < MT_ABS_SIZE; i++) |
| 82 | SETABS(cap, abs[i], absbits, mtdev_mt2abs(i), fd); | 96 | set_info(dev, mtdev_mt2abs(i), absbits, fd); |
| 83 | 97 | ||
| 84 | cap->has_mtdata = has_mt_data(cap); | 98 | dev->has_mtdata = mtdev_has_mt_event(dev, ABS_MT_POSITION_X) && |
| 99 | mtdev_has_mt_event(dev, ABS_MT_POSITION_Y); | ||
| 85 | 100 | ||
| 86 | if (!cap->has_abs[MTDEV_POSITION_X]) | 101 | if (!mtdev_has_mt_event(dev, ABS_MT_POSITION_X)) |
| 87 | getabs(&cap->abs[MTDEV_POSITION_X], ABS_X, fd); | 102 | getabs(get_info(dev, ABS_MT_POSITION_X), ABS_X, fd); |
| 88 | if (!cap->has_abs[MTDEV_POSITION_Y]) | 103 | if (!mtdev_has_mt_event(dev, ABS_MT_POSITION_Y)) |
| 89 | getabs(&cap->abs[MTDEV_POSITION_Y], ABS_Y, fd); | 104 | getabs(get_info(dev, ABS_MT_POSITION_Y), ABS_Y, fd); |
| 90 | if (!cap->has_abs[MTDEV_PRESSURE]) | 105 | if (!mtdev_has_mt_event(dev, ABS_MT_PRESSURE)) |
| 91 | getabs(&cap->abs[MTDEV_PRESSURE], ABS_PRESSURE, fd); | 106 | getabs(get_info(dev, ABS_MT_PRESSURE), ABS_PRESSURE, fd); |
| 92 | 107 | ||
| 93 | if (!cap->has_abs[MTDEV_TRACKING_ID]) { | 108 | if (!mtdev_has_mt_event(dev, ABS_MT_TRACKING_ID)) { |
| 94 | cap->abs[MTDEV_TRACKING_ID].minimum = MT_ID_MIN; | 109 | mtdev_set_abs_minimum(dev, ABS_MT_TRACKING_ID, MT_ID_MIN); |
| 95 | cap->abs[MTDEV_TRACKING_ID].maximum = MT_ID_MAX; | 110 | mtdev_set_abs_maximum(dev, ABS_MT_TRACKING_ID, MT_ID_MAX); |
| 96 | } | 111 | } |
| 97 | 112 | ||
| 98 | default_fuzz(cap, MTDEV_POSITION_X, SN_COORD); | 113 | default_fuzz(dev, ABS_MT_POSITION_X, SN_COORD); |
| 99 | default_fuzz(cap, MTDEV_POSITION_Y, SN_COORD); | 114 | default_fuzz(dev, ABS_MT_POSITION_Y, SN_COORD); |
| 100 | default_fuzz(cap, MTDEV_TOUCH_MAJOR, SN_WIDTH); | 115 | default_fuzz(dev, ABS_MT_TOUCH_MAJOR, SN_WIDTH); |
| 101 | default_fuzz(cap, MTDEV_TOUCH_MINOR, SN_WIDTH); | 116 | default_fuzz(dev, ABS_MT_TOUCH_MINOR, SN_WIDTH); |
| 102 | default_fuzz(cap, MTDEV_WIDTH_MAJOR, SN_WIDTH); | 117 | default_fuzz(dev, ABS_MT_WIDTH_MAJOR, SN_WIDTH); |
| 103 | default_fuzz(cap, MTDEV_WIDTH_MINOR, SN_WIDTH); | 118 | default_fuzz(dev, ABS_MT_WIDTH_MINOR, SN_WIDTH); |
| 104 | default_fuzz(cap, MTDEV_ORIENTATION, SN_ORIENT); | 119 | default_fuzz(dev, ABS_MT_ORIENTATION, SN_ORIENT); |
| 105 | 120 | ||
| 106 | return 0; | 121 | return 0; |
| 107 | } | 122 | } |
| 108 | 123 | ||
| 109 | int mtdev_configure(struct mtdev *dev, int fd) | 124 | int mtdev_has_mt_event(const struct mtdev *dev, int code) |
| 125 | { | ||
| 126 | int ix; | ||
| 127 | |||
| 128 | if (code == ABS_MT_SLOT) | ||
| 129 | return dev->has_slot; | ||
| 130 | if (!mtdev_is_absmt(code)) | ||
| 131 | return 0; | ||
| 132 | |||
| 133 | ix = mtdev_abs2mt(code); | ||
| 134 | if (ix < 11) | ||
| 135 | return dev->has_abs[ix]; | ||
| 136 | else | ||
| 137 | return dev->state->has_ext_abs[ix - 11]; | ||
| 138 | } | ||
| 139 | |||
| 140 | int mtdev_get_abs_minimum(const struct mtdev *dev, int code) | ||
| 110 | { | 141 | { |
| 111 | return read_caps(&dev->caps, fd); | 142 | const struct input_absinfo *abs = get_info((struct mtdev *)dev, code); |
| 143 | return abs ? abs->minimum : 0; | ||
| 112 | } | 144 | } |
| 145 | |||
| 146 | int mtdev_get_abs_maximum(const struct mtdev *dev, int code) | ||
| 147 | { | ||
| 148 | const struct input_absinfo *abs = get_info((struct mtdev *)dev, code); | ||
| 149 | return abs ? abs->maximum : 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | int mtdev_get_abs_fuzz(const struct mtdev *dev, int code) | ||
| 153 | { | ||
| 154 | const struct input_absinfo *abs = get_info((struct mtdev *)dev, code); | ||
| 155 | return abs ? abs->fuzz : 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | int mtdev_get_abs_resolution(const struct mtdev *dev, int code) | ||
| 159 | { | ||
| 160 | const struct input_absinfo *abs = get_info((struct mtdev *)dev, code); | ||
| 161 | return abs ? abs->resolution : 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | void mtdev_set_abs_minimum(struct mtdev *dev, int code, int value) | ||
| 165 | { | ||
| 166 | struct input_absinfo *abs = get_info(dev, code); | ||
| 167 | if (abs) | ||
| 168 | abs->minimum = value; | ||
| 169 | } | ||
| 170 | |||
| 171 | void mtdev_set_mt_event(struct mtdev *dev, int code, int value) | ||
| 172 | { | ||
| 173 | int ix; | ||
| 174 | |||
| 175 | if (code == ABS_MT_SLOT) | ||
| 176 | dev->has_slot = value; | ||
| 177 | if (!mtdev_is_absmt(code)) | ||
| 178 | return; | ||
| 179 | |||
| 180 | ix = mtdev_abs2mt(code); | ||
| 181 | if (ix < 11) | ||
| 182 | dev->has_abs[ix] = value; | ||
| 183 | else | ||
| 184 | dev->state->has_ext_abs[ix - 11] = value; | ||
| 185 | } | ||
| 186 | |||
| 187 | void mtdev_set_abs_maximum(struct mtdev *dev, int code, int value) | ||
| 188 | { | ||
| 189 | struct input_absinfo *abs = get_info(dev, code); | ||
| 190 | if (abs) | ||
| 191 | abs->maximum = value; | ||
| 192 | } | ||
| 193 | |||
| 194 | void mtdev_set_abs_fuzz(struct mtdev *dev, int code, int value) | ||
| 195 | { | ||
| 196 | struct input_absinfo *abs = get_info(dev, code); | ||
| 197 | if (abs) | ||
| 198 | abs->fuzz = value; | ||
| 199 | } | ||
| 200 | |||
| 201 | void mtdev_set_abs_resolution(struct mtdev *dev, int code, int value) | ||
| 202 | { | ||
| 203 | struct input_absinfo *abs = get_info(dev, code); | ||
| 204 | if (abs) | ||
| 205 | abs->resolution = value; | ||
| 206 | } | ||
| 207 | |||
