Hashmap *object_map;
bool async_hotplug : 1;
+ bool hotplug : 1;
bool running : 1;
bool ready : 1;
bool cap_dumb : 1;
if (r == -ENOENT) {
card->async_hotplug = true;
r = 0;
- log_debug("grdrm: %s: plane %u removed during resync", card->base.name, plane->object.id);
+ log_debug("grdrm: %s: plane %u removed during resync",
+ card->base.name, plane->object.id);
} else {
- log_debug("grdrm: %s: cannot retrieve plane %u: %m", card->base.name, plane->object.id);
+ log_debug_errno(errno, "grdrm: %s: cannot retrieve plane %u: %m",
+ card->base.name, plane->object.id);
}
return r;
res.count_encoders = connector->kern.max_encoders;
res.count_props = connector->kern.max_props;
- /* Retrieve modes only if we have none. This avoids expensive
- * EDID reads in the kernel, that can slow down resyncs
- * considerably! */
- if (connector->kern.n_modes == 0) {
- res.modes_ptr = PTR_TO_UINT64(connector->kern.modes);
- res.count_modes = connector->kern.max_modes;
+ /* The kernel reads modes from the EDID information only if we
+ * pass count_modes==0. This is a legacy hack for libdrm (which
+ * called every ioctl twice). Now we have to adopt.. *sigh*.
+ * If we never received an hotplug event, there's no reason to
+ * sync modes. EDID reads are heavy, so skip that if not
+ * required. */
+ if (card->hotplug) {
+ if (tries > 0) {
+ res.modes_ptr = PTR_TO_UINT64(connector->kern.modes);
+ res.count_modes = connector->kern.max_modes;
+ } else {
+ resized = true;
+ }
}
r = ioctl(card->fd, DRM_IOCTL_MODE_GETCONNECTOR, &res);
if (r == -ENOENT) {
card->async_hotplug = true;
r = 0;
- log_debug("grdrm: %s: connector %u removed during resync", card->base.name, connector->object.id);
+ log_debug("grdrm: %s: connector %u removed during resync",
+ card->base.name, connector->object.id);
} else {
- log_debug("grdrm: %s: cannot retrieve connector %u: %m", card->base.name, connector->object.id);
+ log_debug_errno(errno, "grdrm: %s: cannot retrieve connector %u: %m",
+ card->base.name, connector->object.id);
}
return r;
continue;
connector->kern.n_encoders = res.count_encoders;
- connector->kern.n_modes = res.count_modes;
connector->kern.n_props = res.count_props;
connector->kern.type = res.connector_type;
connector->kern.type_id = res.connector_type_id;
connector->kern.mm_width = res.mm_width;
connector->kern.mm_height = res.mm_height;
connector->kern.subpixel = res.subpixel;
+ if (res.modes_ptr == PTR_TO_UINT64(connector->kern.modes))
+ connector->kern.n_modes = res.count_modes;
break;
}
if (r == -ENOENT) {
card->async_hotplug = true;
r = 0;
- log_debug("grdrm: %s: encoder %u removed during resync", card->base.name, encoder->object.id);
+ log_debug("grdrm: %s: encoder %u removed during resync",
+ card->base.name, encoder->object.id);
} else {
- log_debug("grdrm: %s: cannot retrieve encoder %u: %m", card->base.name, encoder->object.id);
+ log_debug_errno(errno, "grdrm: %s: cannot retrieve encoder %u: %m",
+ card->base.name, encoder->object.id);
}
return r;
if (r == -ENOENT) {
card->async_hotplug = true;
r = 0;
- log_debug("grdrm: %s: crtc %u removed during resync", card->base.name, crtc->object.id);
+ log_debug("grdrm: %s: crtc %u removed during resync",
+ card->base.name, crtc->object.id);
} else {
- log_debug("grdrm: %s: cannot retrieve crtc %u: %m", card->base.name, crtc->object.id);
+ log_debug_errno(errno, "grdrm: %s: cannot retrieve crtc %u: %m",
+ card->base.name, crtc->object.id);
}
return r;
grdev_pipe_ready(&crtc->pipe->base, true);
}
-static void grdrm_crtc_commit_deep(grdrm_crtc *crtc, grdev_fb **slot) {
+static void grdrm_crtc_commit_deep(grdrm_crtc *crtc, grdev_fb *basefb) {
struct drm_mode_crtc set_crtc = { .crtc_id = crtc->object.id };
grdrm_card *card = crtc->object.card;
grdrm_pipe *pipe = crtc->pipe;
- grdrm_fb *fb = fb_from_base(*slot);
- size_t i;
+ grdrm_fb *fb;
int r;
assert(crtc);
- assert(slot);
- assert(*slot);
+ assert(basefb);
assert(pipe);
+ fb = fb_from_base(basefb);
+
set_crtc.set_connectors_ptr = PTR_TO_UINT64(crtc->set.connectors);
set_crtc.count_connectors = crtc->set.n_connectors;
set_crtc.fb_id = fb->id;
r = ioctl(card->fd, DRM_IOCTL_MODE_SETCRTC, &set_crtc);
if (r < 0) {
r = -errno;
- log_debug("grdrm: %s: cannot set crtc %" PRIu32 ": %m",
- card->base.name, crtc->object.id);
+ log_debug_errno(errno, "grdrm: %s: cannot set crtc %" PRIu32 ": %m",
+ card->base.name, crtc->object.id);
grdrm_card_async(card, r);
return;
crtc->applied = true;
}
- *slot = NULL;
+ pipe->base.back = NULL;
pipe->base.front = &fb->base;
fb->flipid = 0;
++pipe->counter;
* To avoid duplicating that everywhere, we schedule our own
* timer and raise a fake FRAME event when it fires. */
grdev_pipe_schedule(&pipe->base, 1);
-
- if (!pipe->base.back) {
- for (i = 0; i < pipe->base.max_fbs; ++i) {
- if (!pipe->base.fbs[i])
- continue;
-
- fb = fb_from_base(pipe->base.fbs[i]);
- if (&fb->base == pipe->base.front)
- continue;
-
- fb->flipid = 0;
- pipe->base.back = &fb->base;
- break;
- }
- }
}
-static int grdrm_crtc_commit_flip(grdrm_crtc *crtc, grdev_fb **slot) {
+static int grdrm_crtc_commit_flip(grdrm_crtc *crtc, grdev_fb *basefb) {
struct drm_mode_crtc_page_flip page_flip = { .crtc_id = crtc->object.id };
grdrm_card *card = crtc->object.card;
grdrm_pipe *pipe = crtc->pipe;
- grdrm_fb *fb = fb_from_base(*slot);
+ grdrm_fb *fb;
uint32_t cnt;
- size_t i;
int r;
assert(crtc);
- assert(slot);
- assert(*slot);
+ assert(basefb);
assert(pipe);
- if (!crtc->applied && !grdrm_modes_compatible(&crtc->kern.mode, &crtc->set.mode))
+ if (!crtc->applied) {
+ if (!grdrm_modes_compatible(&crtc->kern.mode, &crtc->set.mode))
+ return 0;
+
+ /* TODO: Theoretically, we should be able to page-flip to our
+ * framebuffer here. We didn't perform any deep modeset, but the
+ * DRM driver is really supposed to reject our page-flip in case
+ * the FB is not compatible. We then properly fall back to a
+ * deep modeset.
+ * As it turns out, drivers don't to this. Therefore, we need to
+ * perform a full modeset on enter now. We might avoid this in
+ * the future with fixed drivers.. */
+
return 0;
+ }
+
+ fb = fb_from_base(basefb);
cnt = ++pipe->counter ? : ++pipe->counter;
page_flip.fb_id = fb->id;
* possible to see whether cards support page-flipping, so
* avoid logging on each frame. */
if (r != -EINVAL)
- log_debug("grdrm: %s: cannot schedule page-flip on crtc %" PRIu32 ": %m",
- card->base.name, crtc->object.id);
+ log_debug_errno(errno, "grdrm: %s: cannot schedule page-flip on crtc %" PRIu32 ": %m",
+ card->base.name, crtc->object.id);
if (grdrm_card_async(card, r))
return r;
pipe->base.flip = false;
pipe->counter = cnt;
fb->flipid = cnt;
- *slot = NULL;
+ pipe->base.back = NULL;
/* Raise fake FRAME event if it takes longer than 2
* frames to receive the pageflip event. We assume the
* queue ran over or some other error happened. */
grdev_pipe_schedule(&pipe->base, 2);
- if (!pipe->base.back) {
- for (i = 0; i < pipe->base.max_fbs; ++i) {
- if (!pipe->base.fbs[i])
- continue;
-
- fb = fb_from_base(pipe->base.fbs[i]);
- if (&fb->base == pipe->base.front)
- continue;
- if (fb->flipid)
- continue;
-
- pipe->base.back = &fb->base;
- break;
- }
- }
-
return 1;
}
struct drm_mode_crtc set_crtc = { .crtc_id = crtc->object.id };
grdrm_card *card = crtc->object.card;
grdrm_pipe *pipe;
- grdev_fb **slot;
+ grdev_fb *fb;
int r;
assert(crtc);
r = ioctl(card->fd, DRM_IOCTL_MODE_SETCRTC, &set_crtc);
if (r < 0) {
r = -errno;
- log_debug("grdrm: %s: cannot shutdown crtc %" PRIu32 ": %m",
- card->base.name, crtc->object.id);
+ log_debug_errno(errno, "grdrm: %s: cannot shutdown crtc %" PRIu32 ": %m",
+ card->base.name, crtc->object.id);
grdrm_card_async(card, r);
return;
assert(crtc->set.n_connectors > 0);
if (pipe->base.flip)
- slot = &pipe->base.back;
+ fb = pipe->base.back;
else if (!crtc->applied)
- slot = &pipe->base.front;
+ fb = pipe->base.front;
else
return;
- if (!*slot)
+ if (!fb)
return;
- r = grdrm_crtc_commit_flip(crtc, slot);
+ r = grdrm_crtc_commit_flip(crtc, fb);
if (r == 0) {
/* in case we couldn't page-flip, perform deep modeset */
- grdrm_crtc_commit_deep(crtc, slot);
+ grdrm_crtc_commit_deep(crtc, fb);
}
}
r = ioctl(card->fd, DRM_IOCTL_MODE_SETCRTC, &set_crtc);
if (r < 0) {
r = -errno;
- log_debug("grdrm: %s: cannot restore crtc %" PRIu32 ": %m",
- card->base.name, crtc->object.id);
+ log_debug_errno(errno, "grdrm: %s: cannot restore crtc %" PRIu32 ": %m",
+ card->base.name, crtc->object.id);
grdrm_card_async(card, r);
return;
static void grdrm_crtc_flip_complete(grdrm_crtc *crtc, uint32_t counter, struct drm_event_vblank *event) {
bool flipped = false;
grdrm_pipe *pipe;
- grdrm_fb *back = NULL;
size_t i;
assert(crtc);
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) {
- back = fb;
}
}
- if (!pipe->base.back)
- pipe->base.back = &back->base;
-
if (flipped) {
crtc->pipe->base.flipping = false;
grdev_pipe_frame(&pipe->base);
r = ioctl(card->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
if (r < 0) {
- r = -errno;
- log_debug("grdrm: %s: cannot create dumb buffer %" PRIu32 "x%" PRIu32": %m",
- card->base.name, fb->base.width, fb->base.height);
+ r = negative_errno();
+ log_debug_errno(errno, "grdrm: %s: cannot create dumb buffer %" PRIu32 "x%" PRIu32": %m",
+ card->base.name, fb->base.width, fb->base.height);
return r;
}
r = ioctl(card->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
if (r < 0) {
- r = -errno;
- log_debug("grdrm: %s: cannot map dumb buffer %" PRIu32 "x%" PRIu32": %m",
- card->base.name, fb->base.width, fb->base.height);
+ r = negative_errno();
+ log_debug_errno(errno, "grdrm: %s: cannot map dumb buffer %" PRIu32 "x%" PRIu32": %m",
+ card->base.name, fb->base.width, fb->base.height);
return r;
}
fb->base.maps[0] = mmap(0, fb->sizes[0], PROT_WRITE, MAP_SHARED, card->fd, map_dumb.offset);
if (fb->base.maps[0] == MAP_FAILED) {
- r = -errno;
- log_debug("grdrm: %s: cannot memory-map dumb buffer %" PRIu32 "x%" PRIu32": %m",
- card->base.name, fb->base.width, fb->base.height);
+ r = negative_errno();
+ log_debug_errno(errno, "grdrm: %s: cannot memory-map dumb buffer %" PRIu32 "x%" PRIu32": %m",
+ card->base.name, fb->base.width, fb->base.height);
return r;
}
r = ioctl(card->fd, DRM_IOCTL_MODE_ADDFB2, &add_fb);
if (r < 0) {
- r = -errno;
- log_debug("grdrm: %s: cannot add framebuffer %" PRIu32 "x%" PRIu32": %m",
- card->base.name, fb->base.width, fb->base.height);
+ r = negative_errno();
+ log_debug_errno(errno, "grdrm: %s: cannot add framebuffer %" PRIu32 "x%" PRIu32": %m",
+ card->base.name, fb->base.width, fb->base.height);
return r;
}
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->base.free_fn)
+ fb->base.free_fn(fb->base.data.ptr);
+
+ if (fb->id > 0 && fb->card->fd >= 0) {
+ r = ioctl(fb->card->fd, DRM_IOCTL_MODE_RMFB, fb->id);
+ if (r < 0)
+ log_debug_errno(errno, "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 = { };
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_errno(errno, "grdrm: %s: cannot destroy dumb-buffer %" PRIu32 ": %m",
+ fb->card->base.name, fb->handles[i]);
}
}
free(pipe);
}
+static grdev_fb *grdrm_pipe_target(grdev_pipe *basepipe) {
+ grdrm_fb *fb;
+ size_t i;
+
+ if (!basepipe->back) {
+ for (i = 0; i < basepipe->max_fbs; ++i) {
+ if (!basepipe->fbs[i])
+ continue;
+
+ fb = fb_from_base(basepipe->fbs[i]);
+ if (&fb->base == basepipe->front)
+ continue;
+ if (basepipe->flipping && fb->flipid)
+ continue;
+
+ basepipe->back = &fb->base;
+ break;
+ }
+ }
+
+ return basepipe->back;
+}
+
+static void grdrm_pipe_enable(grdev_pipe *basepipe) {
+ grdrm_pipe *pipe = grdrm_pipe_from_base(basepipe);
+
+ pipe->crtc->applied = false;
+}
+
+static void grdrm_pipe_disable(grdev_pipe *basepipe) {
+ grdrm_pipe *pipe = grdrm_pipe_from_base(basepipe);
+
+ pipe->crtc->applied = false;
+}
+
static const grdev_pipe_vtable grdrm_pipe_vtable = {
.free = grdrm_pipe_free,
+ .target = grdrm_pipe_target,
+ .enable = grdrm_pipe_enable,
+ .disable = grdrm_pipe_disable,
};
/*
r = ioctl(card->fd, DRM_IOCTL_MODE_GETRESOURCES, &res);
if (r < 0) {
r = -errno;
- log_debug("grdrm: %s: cannot retrieve drm resources: %m", card->base.name);
+ log_debug_errno(errno, "grdrm: %s: cannot retrieve drm resources: %m",
+ card->base.name);
return r;
}
r = ioctl(card->fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &pres);
if (r < 0) {
r = -errno;
- log_debug("grdrm: %s: cannot retrieve drm plane-resources: %m", card->base.name);
+ log_debug_errno(errno, "grdrm: %s: cannot retrieve drm plane-resources: %m",
+ card->base.name);
return r;
}
n = ALIGN_POWER2(max);
if (!n || n > UINT16_MAX) {
- log_debug("grdrm: %s: excessive DRM resource limit: %" PRIu32, card->base.name, max);
+ log_debug("grdrm: %s: excessive DRM resource limit: %" PRIu32,
+ card->base.name, max);
return -ERANGE;
}
card->ready = false;
r = grdrm_card_resync(card);
if (r < 0) {
- log_debug("grdrm: %s/%s: cannot re-sync card: %s",
- card->base.session->name, card->base.name, strerror(-r));
+ log_debug_errno(r, "grdrm: %s/%s: cannot re-sync card: %m",
+ card->base.session->name, card->base.name);
return;
}
grdrm_card_configure(card);
card->ready = true;
+ card->hotplug = false;
grdev_session_unpin(card->base.session);
}
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
if (errno == EAGAIN || errno == EINTR)
return 0;
- log_debug("grdrm: %s/%s: read error: %m", card->base.session->name, card->base.name);
+ log_debug_errno(errno, "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) {
- log_debug("grdrm: %s/%s: truncated event", card->base.session->name, card->base.name);
+ if (len < sizeof(*event) || len < event->length) {
+ log_debug("grdrm: %s/%s: truncated event",
+ card->base.session->name, card->base.name);
break;
}
case DRM_EVENT_FLIP_COMPLETE:
vblank = (void*)event;
if (event->length < sizeof(*vblank)) {
- log_debug("grdrm: %s/%s: truncated vblank event", card->base.session->name, card->base.name);
+ log_debug("grdrm: %s/%s: truncated vblank event",
+ card->base.session->name, card->base.name);
break;
}
sd_event_source_set_enabled(card->fd_src, SD_EVENT_OFF);
+ card->hotplug = true;
card->fd = fd;
fd = -1;
r = ioctl(card->fd, DRM_IOCTL_GET_CAP, &cap);
card->cap_dumb = r >= 0 && cap.value;
if (r < 0)
- log_debug("grdrm: %s/%s: cannot retrieve DUMB_BUFFER capability: %s",
- card->base.session->name, card->base.name, strerror(-r));
+ log_debug_errno(r, "grdrm: %s/%s: cannot retrieve DUMB_BUFFER capability: %m",
+ card->base.session->name, card->base.name);
else if (!card->cap_dumb)
log_debug("grdrm: %s/%s: DUMB_BUFFER capability not supported",
card->base.session->name, card->base.name);
r = ioctl(card->fd, DRM_IOCTL_GET_CAP, &cap);
card->cap_monotonic = r >= 0 && cap.value;
if (r < 0)
- log_debug("grdrm: %s/%s: cannot retrieve TIMESTAMP_MONOTONIC capability: %s",
- card->base.session->name, card->base.name, strerror(-r));
+ log_debug_errno(r, "grdrm: %s/%s: cannot retrieve TIMESTAMP_MONOTONIC capability: %m",
+ card->base.session->name, card->base.name);
else if (!card->cap_monotonic)
log_debug("grdrm: %s/%s: TIMESTAMP_MONOTONIC is disabled globally, fix this NOW!",
card->base.session->name, card->base.name);
fd = open(cu->devnode, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
if (fd < 0) {
/* not fatal; simply ignore the device */
- log_debug("grdrm: %s/%s: cannot open node %s: %m",
- basecard->session->name, basecard->name, cu->devnode);
+ log_debug_errno(errno, "grdrm: %s/%s: cannot open node %s: %m",
+ basecard->session->name, basecard->name, cu->devnode);
return;
}
r = grdrm_card_open(&cu->card, fd);
if (r < 0) {
- log_debug("grdrm: %s/%s: cannot open: %s",
- basecard->session->name, basecard->name, strerror(-r));
+ log_debug_errno(r, "grdrm: %s/%s: cannot open: %m",
+ basecard->session->name, basecard->name);
return;
}
}
r = ioctl(cu->card.fd, DRM_IOCTL_SET_MASTER, 0);
if (r < 0) {
- log_debug("grdrm: %s/%s: cannot acquire DRM-Master: %m",
- basecard->session->name, basecard->name);
+ log_debug_errno(errno, "grdrm: %s/%s: cannot acquire DRM-Master: %m",
+ basecard->session->name, basecard->name);
return;
}
fd = open(cu->devnode, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
if (fd < 0) {
/* not fatal; allow uaccess based control on activation */
- log_debug("grdrm: %s/%s: cannot open node %s: %m",
- basecard->session->name, basecard->name, cu->devnode);
+ log_debug_errno(errno, "grdrm: %s/%s: cannot open node %s: %m",
+ 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_errno(errno, "grdrm: %s/%s: cannot drop DRM-Master: %m",
+ basecard->session->name, basecard->name);
r = grdrm_card_open(&cu->card, fd);
if (r < 0)
- log_debug("grdrm: %s/%s: cannot open: %s",
- basecard->session->name, basecard->name, strerror(-r));
+ log_debug_errno(r, "grdrm: %s/%s: cannot open: %m",
+ basecard->session->name, basecard->name);
}
if (out)
}
if (r < 0)
- log_debug("grdrm: %s/%s: cannot send PauseDeviceComplete: %s",
- session->name, cm->card.base.name, strerror(-r));
+ log_debug_errno(r, "grdrm: %s/%s: cannot send PauseDeviceComplete: %m",
+ session->name, cm->card.base.name);
}
return 0;
* and our code works fine this way. */
fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
if (fd < 0) {
- log_debug("grdrm: %s/%s: cannot duplicate fd: %m",
- session->name, cm->card.base.name);
+ log_debug_errno(errno, "grdrm: %s/%s: cannot duplicate fd: %m",
+ session->name, cm->card.base.name);
return 0;
}
r = grdrm_card_open(&cm->card, fd);
if (r < 0) {
- log_debug("grdrm: %s/%s: cannot open: %s",
- session->name, cm->card.base.name, strerror(-r));
+ log_debug_errno(r, "grdrm: %s/%s: cannot open: %m",
+ session->name, cm->card.base.name);
return 0;
}
}
fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
if (fd < 0) {
- log_debug("grdrm: %s/%s: cannot duplicate fd: %m",
- session->name, cm->card.base.name);
+ log_debug_errno(errno, "grdrm: %s/%s: cannot duplicate fd: %m",
+ session->name, cm->card.base.name);
return 0;
}
r = grdrm_card_open(&cm->card, fd);
if (r < 0) {
- log_debug("grdrm: %s/%s: cannot open: %s",
- session->name, cm->card.base.name, strerror(-r));
+ log_debug_errno(r, "grdrm: %s/%s: cannot open: %m",
+ session->name, cm->card.base.name);
return 0;
}
return;
error:
- log_debug("grdrm: %s/%s: cannot send TakeDevice request: %s",
- session->name, cm->card.base.name, strerror(-r));
+ log_debug_errno(r, "grdrm: %s/%s: cannot send TakeDevice request: %m",
+ session->name, cm->card.base.name);
}
static void managed_card_release_device(managed_card *cm) {
}
if (r < 0 && r != -ENOTCONN)
- log_debug("grdrm: %s/%s: cannot send ReleaseDevice: %s",
- session->name, cm->card.base.name, strerror(-r));
+ log_debug_errno(r, "grdrm: %s/%s: cannot send ReleaseDevice: %m",
+ session->name, cm->card.base.name);
}
static int managed_card_new(grdev_card **out, grdev_session *session, struct udev_device *ud) {
/* If we get add/remove events on DRM nodes without devnum, we
* got hotplugged DRM objects so refresh the device. */
devnum = udev_device_get_devnum(ud);
- if (devnum == 0)
+ if (devnum == 0) {
+ card->hotplug = true;
grdrm_card_hotplug(card);
+ }
} else if (streq_ptr(action, "change")) {
/* A change event with HOTPLUG=1 is sent whenever a connector
* changed state. Refresh the device to update our state. */
p = udev_device_get_property_value(ud, "HOTPLUG");
- if (streq_ptr(p, "1"))
+ if (streq_ptr(p, "1")) {
+ card->hotplug = true;
grdrm_card_hotplug(card);
+ }
}
}