drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id) { struct drm_mode_get_blob blob; drmModePropertyBlobPtr r; blob.length = 0; blob.data = 0; blob.blob_id = blob_id; if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) return NULL; if (blob.length) blob.data = VOID2U64(drmMalloc(blob.length)); if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) { r = NULL; goto err_allocs; } if (!(r = drmMalloc(sizeof(*r)))) goto err_allocs; r->id = blob.blob_id; r->length = blob.length; r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length); err_allocs: drmFree(U642VOID(blob.data)); return r; }
drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id) { struct drm_mode_get_plane ovr, counts; drmModePlanePtr r = 0; retry: memset(&ovr, 0, sizeof(struct drm_mode_get_plane)); ovr.plane_id = plane_id; if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr)) return 0; counts = ovr; if (ovr.count_format_types) { ovr.format_type_ptr = VOID2U64(drmMalloc(ovr.count_format_types * sizeof(uint32_t))); if (!ovr.format_type_ptr) goto err_allocs; } if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr)) goto err_allocs; if (counts.count_format_types < ovr.count_format_types) { drmFree(U642VOID(ovr.format_type_ptr)); goto retry; } if (!(r = drmMalloc(sizeof(*r)))) goto err_allocs; r->count_formats = ovr.count_format_types; r->plane_id = ovr.plane_id; r->crtc_id = ovr.crtc_id; r->fb_id = ovr.fb_id; r->possible_crtcs = ovr.possible_crtcs; r->gamma_size = ovr.gamma_size; r->formats = drmAllocCpy(U642VOID(ovr.format_type_ptr), ovr.count_format_types, sizeof(uint32_t)); if (ovr.count_format_types && !r->formats) { drmFree(r->formats); drmFree(r); r = 0; } err_allocs: drmFree(U642VOID(ovr.format_type_ptr)); return r; }
int drmHandleEvent(int fd, drmEventContextPtr evctx) { char buffer[1024]; int len, i; struct drm_event *e; struct drm_event_vblank *vblank; /* The DRM read semantics guarantees that we always get only * complete events. */ len = read(fd, buffer, sizeof buffer); if (len == 0) return 0; if (len < sizeof *e) return -1; i = 0; while (i < len) { e = (struct drm_event *) &buffer[i]; switch (e->type) { case DRM_EVENT_VBLANK: if (evctx->version < 1 || evctx->vblank_handler == NULL) break; vblank = (struct drm_event_vblank *) e; evctx->vblank_handler(fd, vblank->sequence, vblank->tv_sec, vblank->tv_usec, U642VOID (vblank->user_data)); break; case DRM_EVENT_FLIP_COMPLETE: if (evctx->version < 2 || evctx->page_flip_handler == NULL) break; vblank = (struct drm_event_vblank *) e; evctx->page_flip_handler(fd, vblank->sequence, vblank->tv_sec, vblank->tv_usec, U642VOID (vblank->user_data)); break; default: break; } i += e->length; } return 0; }
drmModePlaneResPtr drmModeGetPlaneResources(int fd) { struct drm_mode_get_plane_res res, counts; drmModePlaneResPtr r = 0; retry: memset(&res, 0, sizeof(struct drm_mode_get_plane_res)); if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res)) return 0; counts = res; if (res.count_planes) { res.plane_id_ptr = VOID2U64(drmMalloc(res.count_planes * sizeof(uint32_t))); if (!res.plane_id_ptr) goto err_allocs; } if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res)) goto err_allocs; if (counts.count_planes < res.count_planes) { drmFree(U642VOID(res.plane_id_ptr)); goto retry; } if (!(r = drmMalloc(sizeof(*r)))) goto err_allocs; r->count_planes = res.count_planes; r->planes = drmAllocCpy(U642VOID(res.plane_id_ptr), res.count_planes, sizeof(uint32_t)); if (res.count_planes && !r->planes) { drmFree(r->planes); drmFree(r); r = 0; } err_allocs: drmFree(U642VOID(res.plane_id_ptr)); return r; }
drmModeResPtr drmModeGetResources(int fd) { struct drm_mode_card_res res; drmModeResPtr r = 0; memset(&res, 0, sizeof(struct drm_mode_card_res)); if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) return 0; if (res.count_fbs) res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t))); if (res.count_crtcs) res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t))); if (res.count_connectors) res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t))); if (res.count_encoders) res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t))); if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) { r = NULL; goto err_allocs; } /* * return */ if (!(r = drmMalloc(sizeof(*r)))) return 0; r->min_width = res.min_width; r->max_width = res.max_width; r->min_height = res.min_height; r->max_height = res.max_height; r->count_fbs = res.count_fbs; r->count_crtcs = res.count_crtcs; r->count_connectors = res.count_connectors; r->count_encoders = res.count_encoders; /* TODO we realy should test if these allocs fails. */ r->fbs = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t)); r->crtcs = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t)); r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t)); r->encoders = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t)); err_allocs: drmFree(U642VOID(res.fb_id_ptr)); drmFree(U642VOID(res.crtc_id_ptr)); drmFree(U642VOID(res.connector_id_ptr)); drmFree(U642VOID(res.encoder_id_ptr)); return r; }
drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, uint32_t object_id, uint32_t object_type) { struct drm_mode_obj_get_properties properties; drmModeObjectPropertiesPtr ret = NULL; uint32_t count; retry: memset(&properties, 0, sizeof(struct drm_mode_obj_get_properties)); properties.obj_id = object_id; properties.obj_type = object_type; if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)) return 0; count = properties.count_props; if (count) { properties.props_ptr = VOID2U64(drmMalloc(count * sizeof(uint32_t))); if (!properties.props_ptr) goto err_allocs; properties.prop_values_ptr = VOID2U64(drmMalloc(count * sizeof(uint64_t))); if (!properties.prop_values_ptr) goto err_allocs; } if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)) goto err_allocs; if (count < properties.count_props) { drmFree(U642VOID(properties.props_ptr)); drmFree(U642VOID(properties.prop_values_ptr)); goto retry; } count = properties.count_props; ret = drmMalloc(sizeof(*ret)); if (!ret) goto err_allocs; ret->count_props = count; ret->props = drmAllocCpy(U642VOID(properties.props_ptr), count, sizeof(uint32_t)); ret->prop_values = drmAllocCpy(U642VOID(properties.prop_values_ptr), count, sizeof(uint64_t)); if (ret->count_props && (!ret->props || !ret->prop_values)) { drmFree(ret->props); drmFree(ret->prop_values); drmFree(ret); ret = NULL; } err_allocs: drmFree(U642VOID(properties.props_ptr)); drmFree(U642VOID(properties.prop_values_ptr)); return ret; }
drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) { struct drm_mode_get_property prop; drmModePropertyPtr r; VG_CLEAR(prop); prop.prop_id = property_id; prop.count_enum_blobs = 0; prop.count_values = 0; prop.flags = 0; prop.enum_blob_ptr = 0; prop.values_ptr = 0; if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) return 0; if (prop.count_values) prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t))); if (prop.count_enum_blobs && (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK))) prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum))); if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) { prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); } if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) { r = NULL; goto err_allocs; } if (!(r = drmMalloc(sizeof(*r)))) return NULL; r->prop_id = prop.prop_id; r->count_values = prop.count_values; r->flags = prop.flags; if (prop.count_values) r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t)); if (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { r->count_enums = prop.count_enum_blobs; r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum)); } else if (prop.flags & DRM_MODE_PROP_BLOB) { r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t)); r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t)); r->count_blobs = prop.count_enum_blobs; } strncpy(r->name, prop.name, DRM_PROP_NAME_LEN); r->name[DRM_PROP_NAME_LEN-1] = 0; err_allocs: drmFree(U642VOID(prop.values_ptr)); drmFree(U642VOID(prop.enum_blob_ptr)); return r; }
drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) { struct drm_mode_get_connector conn, counts; drmModeConnectorPtr r = NULL; retry: memset(&conn, 0, sizeof(struct drm_mode_get_connector)); conn.connector_id = connector_id; if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) return 0; counts = conn; if (conn.count_props) { conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t))); if (!conn.props_ptr) goto err_allocs; conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t))); if (!conn.prop_values_ptr) goto err_allocs; } if (conn.count_modes) { conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo))); if (!conn.modes_ptr) goto err_allocs; } if (conn.count_encoders) { conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t))); if (!conn.encoders_ptr) goto err_allocs; } if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) goto err_allocs; /* The number of available connectors and etc may have changed with a * hotplug event in between the ioctls, in which case the field is * silently ignored by the kernel. */ if (counts.count_props < conn.count_props || counts.count_modes < conn.count_modes || counts.count_encoders < conn.count_encoders) { drmFree(U642VOID(conn.props_ptr)); drmFree(U642VOID(conn.prop_values_ptr)); drmFree(U642VOID(conn.modes_ptr)); drmFree(U642VOID(conn.encoders_ptr)); goto retry; } if(!(r = drmMalloc(sizeof(*r)))) { goto err_allocs; } r->connector_id = conn.connector_id; r->encoder_id = conn.encoder_id; r->connection = conn.connection; r->mmWidth = conn.mm_width; r->mmHeight = conn.mm_height; /* convert subpixel from kernel to userspace */ r->subpixel = conn.subpixel + 1; r->count_modes = conn.count_modes; r->count_props = conn.count_props; r->props = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t)); r->prop_values = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t)); r->modes = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo)); r->count_encoders = conn.count_encoders; r->encoders = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t)); r->connector_type = conn.connector_type; r->connector_type_id = conn.connector_type_id; if ((r->count_props && !r->props) || (r->count_props && !r->prop_values) || (r->count_modes && !r->modes) || (r->count_encoders && !r->encoders)) { drmFree(r->props); drmFree(r->prop_values); drmFree(r->modes); drmFree(r->encoders); drmFree(r); r = 0; } err_allocs: drmFree(U642VOID(conn.prop_values_ptr)); drmFree(U642VOID(conn.props_ptr)); drmFree(U642VOID(conn.modes_ptr)); drmFree(U642VOID(conn.encoders_ptr)); return r; }
drmModeResPtr drmModeGetResources(int fd) { struct drm_mode_card_res res, counts; drmModeResPtr r = 0; retry: memset(&res, 0, sizeof(struct drm_mode_card_res)); if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) return 0; counts = res; if (res.count_fbs) { res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t))); if (!res.fb_id_ptr) goto err_allocs; } if (res.count_crtcs) { res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t))); if (!res.crtc_id_ptr) goto err_allocs; } if (res.count_connectors) { res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t))); if (!res.connector_id_ptr) goto err_allocs; } if (res.count_encoders) { res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t))); if (!res.encoder_id_ptr) goto err_allocs; } if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) goto err_allocs; /* The number of available connectors and etc may have changed with a * hotplug event in between the ioctls, in which case the field is * silently ignored by the kernel. */ if (counts.count_fbs < res.count_fbs || counts.count_crtcs < res.count_crtcs || counts.count_connectors < res.count_connectors || counts.count_encoders < res.count_encoders) { drmFree(U642VOID(res.fb_id_ptr)); drmFree(U642VOID(res.crtc_id_ptr)); drmFree(U642VOID(res.connector_id_ptr)); drmFree(U642VOID(res.encoder_id_ptr)); goto retry; } /* * return */ if (!(r = drmMalloc(sizeof(*r)))) goto err_allocs; r->min_width = res.min_width; r->max_width = res.max_width; r->min_height = res.min_height; r->max_height = res.max_height; r->count_fbs = res.count_fbs; r->count_crtcs = res.count_crtcs; r->count_connectors = res.count_connectors; r->count_encoders = res.count_encoders; r->fbs = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t)); r->crtcs = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t)); r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t)); r->encoders = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t)); if ((res.count_fbs && !r->fbs) || (res.count_crtcs && !r->crtcs) || (res.count_connectors && !r->connectors) || (res.count_encoders && !r->encoders)) { drmFree(r->fbs); drmFree(r->crtcs); drmFree(r->connectors); drmFree(r->encoders); drmFree(r); r = 0; } err_allocs: drmFree(U642VOID(res.fb_id_ptr)); drmFree(U642VOID(res.crtc_id_ptr)); drmFree(U642VOID(res.connector_id_ptr)); drmFree(U642VOID(res.encoder_id_ptr)); return r; }
drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) { struct drm_mode_get_connector conn; drmModeConnectorPtr r = NULL; conn.connector_id = connector_id; conn.connector_type_id = 0; conn.connector_type = 0; conn.count_modes = 0; conn.modes_ptr = 0; conn.count_props = 0; conn.props_ptr = 0; conn.prop_values_ptr = 0; conn.count_encoders = 0; conn.encoders_ptr = 0; if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) return 0; if (conn.count_props) { conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t))); conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t))); } if (conn.count_modes) conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo))); if (conn.count_encoders) conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t))); if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) goto err_allocs; if(!(r = drmMalloc(sizeof(*r)))) { goto err_allocs; } r->connector_id = conn.connector_id; r->encoder_id = conn.encoder_id; r->connection = conn.connection; r->mmWidth = conn.mm_width; r->mmHeight = conn.mm_height; /* convert subpixel from kernel to userspace */ r->subpixel = conn.subpixel + 1; r->count_modes = conn.count_modes; /* TODO we should test if these alloc & cpy fails. */ r->count_props = conn.count_props; r->props = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t)); r->prop_values = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t)); r->modes = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo)); r->count_encoders = conn.count_encoders; r->encoders = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t)); r->connector_type = conn.connector_type; r->connector_type_id = conn.connector_type_id; if (!r->props || !r->prop_values || !r->modes || !r->encoders) goto err_allocs; err_allocs: drmFree(U642VOID(conn.prop_values_ptr)); drmFree(U642VOID(conn.props_ptr)); drmFree(U642VOID(conn.modes_ptr)); drmFree(U642VOID(conn.encoders_ptr)); return r; }
drm_public int drmHandleEvent(int fd, drmEventContextPtr evctx) { char buffer[1024]; int len, i; struct drm_event *e; struct drm_event_vblank *vblank; struct drm_event_crtc_sequence *seq; void *user_data; /* The DRM read semantics guarantees that we always get only * complete events. */ len = read(fd, buffer, sizeof buffer); if (len == 0) return 0; if (len < (int)sizeof *e) return -1; i = 0; while (i < len) { e = (struct drm_event *)(buffer + i); switch (e->type) { case DRM_EVENT_VBLANK: if (evctx->version < 1 || evctx->vblank_handler == NULL) break; vblank = (struct drm_event_vblank *) e; evctx->vblank_handler(fd, vblank->sequence, vblank->tv_sec, vblank->tv_usec, U642VOID (vblank->user_data)); break; case DRM_EVENT_FLIP_COMPLETE: vblank = (struct drm_event_vblank *) e; user_data = U642VOID (vblank->user_data); if (evctx->version >= 3 && evctx->page_flip_handler2) evctx->page_flip_handler2(fd, vblank->sequence, vblank->tv_sec, vblank->tv_usec, vblank->crtc_id, user_data); else if (evctx->version >= 2 && evctx->page_flip_handler) evctx->page_flip_handler(fd, vblank->sequence, vblank->tv_sec, vblank->tv_usec, user_data); break; case DRM_EVENT_CRTC_SEQUENCE: seq = (struct drm_event_crtc_sequence *) e; if (evctx->version >= 4 && evctx->sequence_handler) evctx->sequence_handler(fd, seq->sequence, seq->time_ns, seq->user_data); break; default: break; } i += e->length; } return 0; }
/* * Destroy a exynos buffer object. * * @bo: a exynos buffer object to be destroyed. */ drm_public void exynos_bo_destroy(struct exynos_bo *bo) { if (!bo) return; if (bo->vaddr) munmap(bo->vaddr, bo->size); if (bo->handle) { struct drm_gem_close req = { .handle = bo->handle, }; drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req); } free(bo); } /* * Get a exynos buffer object from a gem global object name. * * @dev: a exynos device object. * @name: a gem global object name exported by another process. * * this interface is used to get a exynos buffer object from a gem * global object name sent by another process for buffer sharing. * * if true, return a exynos buffer object else NULL. * */ drm_public struct exynos_bo * exynos_bo_from_name(struct exynos_device *dev, uint32_t name) { struct exynos_bo *bo; struct drm_gem_open req = { .name = name, }; bo = calloc(sizeof(*bo), 1); if (!bo) { fprintf(stderr, "failed to allocate bo[%s].\n", strerror(errno)); return NULL; } if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) { fprintf(stderr, "failed to open gem object[%s].\n", strerror(errno)); goto err_free_bo; } bo->dev = dev; bo->name = name; bo->handle = req.handle; return bo; err_free_bo: free(bo); return NULL; } /* * Get a gem global object name from a gem object handle. * * @bo: a exynos buffer object including gem handle. * @name: a gem global object name to be got by kernel driver. * * this interface is used to get a gem global object name from a gem object * handle to a buffer that wants to share it with another process. * * if true, return 0 else negative. */ drm_public int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name) { if (!bo->name) { struct drm_gem_flink req = { .handle = bo->handle, }; int ret; ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req); if (ret) { fprintf(stderr, "failed to get gem global name[%s].\n", strerror(errno)); return ret; } bo->name = req.name; } *name = bo->name; return 0; } drm_public uint32_t exynos_bo_handle(struct exynos_bo *bo) { return bo->handle; } /* * Mmap a buffer to user space. * * @bo: a exynos buffer object including a gem object handle to be mmapped * to user space. * * if true, user pointer mmapped else NULL. */ drm_public void *exynos_bo_map(struct exynos_bo *bo) { if (!bo->vaddr) { struct exynos_device *dev = bo->dev; struct drm_mode_map_dumb arg; void *map = NULL; int ret; memset(&arg, 0, sizeof(arg)); arg.handle = bo->handle; ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg); if (ret) { fprintf(stderr, "failed to map dumb buffer[%s].\n", strerror(errno)); return NULL; } map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, dev->fd, arg.offset); if (map != MAP_FAILED) bo->vaddr = map; } return bo->vaddr; } /* * Export gem object to dmabuf as file descriptor. * * @dev: exynos device object * @handle: gem handle to export as file descriptor of dmabuf * @fd: file descriptor returned from kernel * * @return: 0 on success, -1 on error, and errno will be set */ drm_public int exynos_prime_handle_to_fd(struct exynos_device *dev, uint32_t handle, int *fd) { return drmPrimeHandleToFD(dev->fd, handle, 0, fd); } /* * Import file descriptor into gem handle. * * @dev: exynos device object * @fd: file descriptor of dmabuf to import * @handle: gem handle returned from kernel * * @return: 0 on success, -1 on error, and errno will be set */ drm_public int exynos_prime_fd_to_handle(struct exynos_device *dev, int fd, uint32_t *handle) { return drmPrimeFDToHandle(dev->fd, fd, handle); } /* * Request Wireless Display connection or disconnection. * * @dev: a exynos device object. * @connect: indicate whether connectoin or disconnection request. * @ext: indicate whether edid data includes extensions data or not. * @edid: a pointer to edid data from Wireless Display device. * * this interface is used to request Virtual Display driver connection or * disconnection. for this, user should get a edid data from the Wireless * Display device and then send that data to kernel driver with connection * request * * if true, return 0 else negative. */ drm_public int exynos_vidi_connection(struct exynos_device *dev, uint32_t connect, uint32_t ext, void *edid) { struct drm_exynos_vidi_connection req = { .connection = connect, .extensions = ext, .edid = (uint64_t)(uintptr_t)edid, }; int ret; ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &req); if (ret) { fprintf(stderr, "failed to request vidi connection[%s].\n", strerror(errno)); return ret; } return 0; } static void exynos_handle_vendor(int fd, struct drm_event *e, void *ctx) { struct drm_exynos_g2d_event *g2d; struct exynos_event_context *ectx = ctx; switch (e->type) { case DRM_EXYNOS_G2D_EVENT: if (ectx->version < 1 || ectx->g2d_event_handler == NULL) break; g2d = (struct drm_exynos_g2d_event *)e; ectx->g2d_event_handler(fd, g2d->cmdlist_no, g2d->tv_sec, g2d->tv_usec, U642VOID(g2d->user_data)); break; default: break; } } drm_public int exynos_handle_event(struct exynos_device *dev, struct exynos_event_context *ctx) { char buffer[1024]; int len, i; struct drm_event *e; struct drm_event_vblank *vblank; drmEventContextPtr evctx = &ctx->base; /* The DRM read semantics guarantees that we always get only * complete events. */ len = read(dev->fd, buffer, sizeof buffer); if (len == 0) return 0; if (len < (int)sizeof *e) return -1; i = 0; while (i < len) { e = (struct drm_event *)(buffer + i); switch (e->type) { case DRM_EVENT_VBLANK: if (evctx->version < 1 || evctx->vblank_handler == NULL) break; vblank = (struct drm_event_vblank *) e; evctx->vblank_handler(dev->fd, vblank->sequence, vblank->tv_sec, vblank->tv_usec, U642VOID (vblank->user_data)); break; case DRM_EVENT_FLIP_COMPLETE: if (evctx->version < 2 || evctx->page_flip_handler == NULL) break; vblank = (struct drm_event_vblank *) e; evctx->page_flip_handler(dev->fd, vblank->sequence, vblank->tv_sec, vblank->tv_usec, U642VOID (vblank->user_data)); break; default: exynos_handle_vendor(dev->fd, e, evctx); break; } i += e->length; } return 0; }