/* SPDX-License-Identifier: BSD-2-Clause */ /* * dmabuf_capture.c — daemon-side CAPTURE-plane dmabuf access. */ #include "dmabuf_capture.h" #include "log.h" #include #include #include #include #include #include #include int daedalus_capture_planes_open(int chardev_fd, uint32_t cookie, const struct daedalus_req_decode *req, struct daedalus_capture_planes *out) { int i; int rc; memset(out, 0, sizeof(*out)); for (i = 0; i < DAEDALUS_MAX_CAPTURE_PLANES; i++) out->fd[i] = -1; if (req->capture_num_planes == 0 || req->capture_num_planes > DAEDALUS_MAX_CAPTURE_PLANES) { log_err("dmabuf_capture: bad num_planes=%u", req->capture_num_planes); return -EINVAL; } out->nr = (int) req->capture_num_planes; for (i = 0; i < out->nr; i++) { struct daedalus_get_dmabuf gd = { .cookie = cookie, .plane = (uint32_t) i, /* * O_RDWR is required so the kernel exports the * dmabuf in a mode that allows PROT_READ | * PROT_WRITE mmap. vb2_core_expbuf extracts * the access mode (O_ACCMODE) from flags and * hands it to the memop's get_dmabuf; default * (O_RDONLY) gives mmap -EACCES on writes. */ .flags = O_RDWR | O_CLOEXEC, .fd = -1, }; size_t size = req->capture_plane_size[i]; if (size == 0) { log_err("dmabuf_capture: cookie=%u plane=%d size=0", cookie, i); rc = -EINVAL; goto fail; } if (ioctl(chardev_fd, DAEDALUS_IOC_GET_DMABUF, &gd) < 0) { rc = -errno; log_err("dmabuf_capture: GET_DMABUF cookie=%u plane=%d: %s", cookie, i, strerror(errno)); goto fail; } out->fd[i] = gd.fd; out->size[i] = size; out->stride[i] = req->capture_plane_stride[i]; out->base[i] = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, gd.fd, 0); if (out->base[i] == MAP_FAILED) { rc = -errno; log_err("dmabuf_capture: mmap cookie=%u plane=%d size=%zu: %s", cookie, i, size, strerror(errno)); out->base[i] = NULL; goto fail; } } return 0; fail: daedalus_capture_planes_close(out); return rc; } void daedalus_capture_planes_close(struct daedalus_capture_planes *p) { int i; if (!p) return; for (i = 0; i < DAEDALUS_MAX_CAPTURE_PLANES; i++) { if (p->base[i] && p->base[i] != MAP_FAILED) { munmap(p->base[i], p->size[i]); p->base[i] = NULL; } if (p->fd[i] >= 0) { close(p->fd[i]); p->fd[i] = -1; } } p->nr = 0; }