diff options
| author | Henrik Rydberg <rydberg@euromail.se> | 2010-12-22 18:29:00 +0100 |
|---|---|---|
| committer | Henrik Rydberg <rydberg@euromail.se> | 2010-12-22 18:29:00 +0100 |
| commit | 56a77e68fb91eef928d8a95c50ae14508e37ae0f (patch) | |
| tree | 51af9bb9dd508bca58e8b9416479e79f8bb7ee10 /src/caps.c | |
| parent | 0e2ab3b5940e70493aaabdfe5e8da1c75db4db72 (diff) | |
Introduce a stable ABI
The current mtdev is not ABI stable, and the upcoming additions
to the kernel api will break ABI. This patch starts the process
of keeping binary compatibility with old programs, by moving the
abi-specific parts under a special flag, MTDEV_NO_LEGACY_API,
and makes sure the internal parts compiles with MTDEV_NO_LEGACY_API
set. This way, older programs will still work, old programs will
still compile, and new programs will be able to use the additions.
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
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 | |||
