evdev: prevent unterminated device name
[platform/upstream/libinput.git] / src / evdev.c
index 9289b1c..27296f8 100644 (file)
@@ -20,6 +20,8 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <linux/input.h>
@@ -81,6 +83,11 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time)
                                         WL_POINTER_BUTTON_STATE_RELEASED);
                break;
 
+       case BTN_TOUCH:
+               if (e->value == 0 && !device->is_mt)
+                       notify_touch(device->seat, time, device->mt.slot, 0, 0,
+                                    WL_TOUCH_UP);
+               break;
        default:
                notify_key(device->seat,
                           time, e->code,
@@ -110,15 +117,13 @@ evdev_process_touch(struct evdev_device *device, struct input_event *e)
        case ABS_MT_POSITION_X:
                device->mt.x[device->mt.slot] =
                        (e->value - device->abs.min_x) * screen_width /
-                       (device->abs.max_x - device->abs.min_x) +
-                       device->output->x;
+                       (device->abs.max_x - device->abs.min_x);
                device->pending_events |= EVDEV_ABSOLUTE_MT_MOTION;
                break;
        case ABS_MT_POSITION_Y:
                device->mt.y[device->mt.slot] =
                        (e->value - device->abs.min_y) * screen_height /
-                       (device->abs.max_y - device->abs.min_y) +
-                       device->output->y;
+                       (device->abs.max_y - device->abs.min_y);
                device->pending_events |= EVDEV_ABSOLUTE_MT_MOTION;
                break;
        }
@@ -135,15 +140,13 @@ evdev_process_absolute_motion(struct evdev_device *device,
        case ABS_X:
                device->abs.x =
                        (e->value - device->abs.min_x) * screen_width /
-                       (device->abs.max_x - device->abs.min_x) +
-                       device->output->x;
+                       (device->abs.max_x - device->abs.min_x);
                device->pending_events |= EVDEV_ABSOLUTE_MOTION;
                break;
        case ABS_Y:
                device->abs.y =
                        (e->value - device->abs.min_y) * screen_height /
-                       (device->abs.max_y - device->abs.min_y) +
-                       device->output->y;
+                       (device->abs.max_y - device->abs.min_y);
                device->pending_events |= EVDEV_ABSOLUTE_MOTION;
                break;
        }
@@ -232,26 +235,34 @@ is_motion_event(struct input_event *e)
 static void
 transform_absolute(struct evdev_device *device)
 {
+       int32_t x, y;
+
        if (!device->abs.apply_calibration)
                return;
 
-       device->abs.x = device->abs.x * device->abs.calibration[0] +
-                       device->abs.y * device->abs.calibration[1] +
-                       device->abs.calibration[2];
+       x = device->abs.x * device->abs.calibration[0] +
+               device->abs.y * device->abs.calibration[1] +
+               device->abs.calibration[2];
+
+       y = device->abs.x * device->abs.calibration[3] +
+               device->abs.y * device->abs.calibration[4] +
+               device->abs.calibration[5];
 
-       device->abs.y = device->abs.x * device->abs.calibration[3] +
-                       device->abs.y * device->abs.calibration[4] +
-                       device->abs.calibration[5];
+       device->abs.x = x;
+       device->abs.y = y;
 }
 
 static void
 evdev_flush_motion(struct evdev_device *device, uint32_t time)
 {
        struct weston_seat *master = device->seat;
+       wl_fixed_t x, y;
+       int slot;
 
        if (!(device->pending_events & EVDEV_SYN))
                return;
 
+       slot = device->mt.slot;
        device->pending_events &= ~EVDEV_SYN;
        if (device->pending_events & EVDEV_RELATIVE_MOTION) {
                notify_motion(master, time, device->rel.dx, device->rel.dy);
@@ -260,20 +271,22 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time)
                device->rel.dy = 0;
        }
        if (device->pending_events & EVDEV_ABSOLUTE_MT_DOWN) {
+               weston_output_transform_coordinate(device->output,
+                                                  device->mt.x[slot],
+                                                  device->mt.y[slot],
+                                                  &x, &y);
                notify_touch(master, time,
-                            device->mt.slot,
-                            wl_fixed_from_int(device->mt.x[device->mt.slot]),
-                            wl_fixed_from_int(device->mt.y[device->mt.slot]),
-                            WL_TOUCH_DOWN);
+                            device->mt.slot, x, y, WL_TOUCH_DOWN);
                device->pending_events &= ~EVDEV_ABSOLUTE_MT_DOWN;
                device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION;
        }
        if (device->pending_events & EVDEV_ABSOLUTE_MT_MOTION) {
+               weston_output_transform_coordinate(device->output,
+                                                  device->mt.x[slot],
+                                                  device->mt.y[slot],
+                                                  &x, &y);
                notify_touch(master, time,
-                            device->mt.slot,
-                            wl_fixed_from_int(device->mt.x[device->mt.slot]),
-                            wl_fixed_from_int(device->mt.y[device->mt.slot]),
-                            WL_TOUCH_MOTION);
+                            device->mt.slot, x, y, WL_TOUCH_MOTION);
                device->pending_events &= ~EVDEV_ABSOLUTE_MT_DOWN;
                device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION;
        }
@@ -284,9 +297,19 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time)
        }
        if (device->pending_events & EVDEV_ABSOLUTE_MOTION) {
                transform_absolute(device);
-               notify_motion_absolute(master, time,
-                             wl_fixed_from_int(device->abs.x),
-                             wl_fixed_from_int(device->abs.y));
+               weston_output_transform_coordinate(device->output,
+                                                  device->abs.x,
+                                                  device->abs.y, &x, &y);
+
+               if (device->caps & EVDEV_TOUCH) {
+                       if (master->num_tp == 0)
+                               notify_touch(master, time, 0,
+                                            x, y, WL_TOUCH_DOWN);
+                       else
+                               notify_touch(master, time, 0,
+                                            x, y, WL_TOUCH_MOTION);
+               } else
+                       notify_motion_absolute(master, time, x, y);
                device->pending_events &= ~EVDEV_ABSOLUTE_MOTION;
        }
 }
@@ -431,7 +454,11 @@ evdev_handle_device(struct evdev_device *device)
                        device->abs.max_y = absinfo.maximum;
                        device->caps |= EVDEV_MOTION_ABS;
                }
-               if (TEST_BIT(abs_bits, ABS_MT_SLOT)) {
+                /* We only handle the slotted Protocol B in weston.
+                   Devices with ABS_MT_POSITION_* but not ABS_MT_SLOT
+                   require mtdev for conversion. */
+               if (TEST_BIT(abs_bits, ABS_MT_POSITION_X) &&
+                   TEST_BIT(abs_bits, ABS_MT_POSITION_Y)) {
                        ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_X),
                              &absinfo);
                        device->abs.min_x = absinfo.minimum;
@@ -473,6 +500,10 @@ evdev_handle_device(struct evdev_device *device)
                                break;
                        }
                }
+               if (TEST_BIT(key_bits, BTN_TOUCH)) {
+                       device->caps |= EVDEV_TOUCH;
+               }
+
        }
        if (TEST_BIT(ev_bits, EV_LED)) {
                device->caps |= EVDEV_KEYBOARD;
@@ -525,10 +556,9 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd)
        struct weston_compositor *ec;
        char devname[256] = "unknown";
 
-       device = malloc(sizeof *device);
+       device = zalloc(sizeof *device);
        if (device == NULL)
                return NULL;
-       memset(device, 0, sizeof *device);
 
        ec = seat->compositor;
        device->output =
@@ -545,6 +575,7 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd)
        device->fd = device_fd;
 
        ioctl(device->fd, EVIOCGNAME(sizeof(devname)), devname);
+       devname[sizeof(devname) - 1] = '\0';
        device->devname = strdup(devname);
 
        if (!evdev_handle_device(device)) {