chiark / gitweb /
terminal/grdev: simplify DRM event parsing
[elogind.git] / src / libsystemd-terminal / grdev-drm.c
index 2e55ad326b15ff3484b52179949673a2497267e0..6b130116d7c4011204d6cc527484818a27bc8222 100644 (file)
@@ -1362,10 +1362,9 @@ static void grdrm_crtc_flip_complete(grdrm_crtc *crtc, uint32_t counter, struct
                 fb = fb_from_base(pipe->base.fbs[i]);
                 if (counter != 0 && counter == pipe->counter && fb->flipid == counter) {
                         pipe->base.front = &fb->base;
+                        fb->flipid = 0;
                         flipped = true;
-                }
-
-                if (counter - fb->flipid < UINT16_MAX) {
+                } else if (counter - fb->flipid < UINT16_MAX) {
                         fb->flipid = 0;
                         back = fb;
                 } else if (fb->flipid == 0) {
@@ -1373,7 +1372,7 @@ static void grdrm_crtc_flip_complete(grdrm_crtc *crtc, uint32_t counter, struct
                 }
         }
 
-        if (!pipe->base.back)
+        if (!pipe->base.back && back)
                 pipe->base.back = &back->base;
 
         if (flipped) {
@@ -1474,14 +1473,19 @@ static int grdrm_fb_new(grdrm_fb **out, grdrm_card *card, const struct drm_mode_
 
 grdrm_fb *grdrm_fb_free(grdrm_fb *fb) {
         unsigned int i;
+        int r;
 
         if (!fb)
                 return NULL;
 
         assert(fb->card);
 
-        if (fb->id > 0 && fb->card->fd >= 0)
-                ioctl(fb->card->fd, DRM_IOCTL_MODE_RMFB, fb->id);
+        if (fb->id > 0 && fb->card->fd >= 0) {
+                r = ioctl(fb->card->fd, DRM_IOCTL_MODE_RMFB, fb->id);
+                if (r < 0)
+                        log_debug("grdrm: %s: cannot delete framebuffer %" PRIu32 ": %m",
+                                  fb->card->base.name, fb->id);
+        }
 
         for (i = 0; i < ELEMENTSOF(fb->handles); ++i) {
                 struct drm_mode_destroy_dumb destroy_dumb = { };
@@ -1491,7 +1495,10 @@ grdrm_fb *grdrm_fb_free(grdrm_fb *fb) {
 
                 if (fb->handles[i] > 0 && fb->card->fd >= 0) {
                         destroy_dumb.handle = fb->handles[i];
-                        ioctl(fb->card->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
+                        r = ioctl(fb->card->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
+                        if (r < 0)
+                                log_debug("grdrm: %s: cannot destroy dumb-buffer %" PRIu32 ": %m",
+                                          fb->card->base.name, fb->handles[i]);
                 }
         }
 
@@ -2188,7 +2195,8 @@ static int grdrm_card_io_fn(sd_event_source *s, int fd, uint32_t revents, void *
         uint32_t id, counter;
         grdrm_object *object;
         char buf[4096];
-        ssize_t l, i;
+        size_t len;
+        ssize_t l;
 
         if (revents & (EPOLLHUP | EPOLLERR)) {
                 /* Immediately close device on HUP; no need to flush pending
@@ -2207,15 +2215,12 @@ static int grdrm_card_io_fn(sd_event_source *s, int fd, uint32_t revents, void *
                         log_debug("grdrm: %s/%s: read error: %m", card->base.session->name, card->base.name);
                         grdrm_card_close(card);
                         return 0;
-                } else if ((size_t)l < sizeof(*event)) {
-                        log_debug("grdrm: %s/%s: short read of %zd bytes", card->base.session->name, card->base.name, l);
-                        return 0;
                 }
 
-                for (i = 0; i < l; i += event->length) {
-                        event = (void*)&buf[i];
+                for (len = l; len > 0; len -= event->length) {
+                        event = (void*)buf;
 
-                        if (i + event->length > l) {
+                        if (len < sizeof(*event) || len < event->length) {
                                 log_debug("grdrm: %s/%s: truncated event", card->base.session->name, card->base.name);
                                 break;
                         }
@@ -2549,8 +2554,13 @@ static int unmanaged_card_new(grdev_card **out, grdev_session *session, struct u
                           basecard->session->name, basecard->name, cu->devnode);
         } else {
                 /* We might get DRM-Master implicitly on open(); drop it immediately
-                 * so we acquire it only once we're actually enabled. */
-                ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
+                 * so we acquire it only once we're actually enabled. We don't
+                 * really care whether this call fails or not, but lets log any
+                 * weird errors, anyway. */
+                r = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
+                if (r < 0 && errno != EACCES && errno != EINVAL)
+                        log_debug("grdrm: %s/%s: cannot drop DRM-Master: %m",
+                                  basecard->session->name, basecard->name);
 
                 r = grdrm_card_open(&cu->card, fd);
                 if (r < 0)