From patchwork Fri Apr 27 11:31:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Foss X-Patchwork-Id: 10368203 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2E14D602DC for ; Fri, 27 Apr 2018 11:31:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1D4542937B for ; Fri, 27 Apr 2018 11:31:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 11AD62937D; Fri, 27 Apr 2018 11:31:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 71EF12937B for ; Fri, 27 Apr 2018 11:31:52 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 58D396E8CA; Fri, 27 Apr 2018 11:31:51 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by gabe.freedesktop.org (Postfix) with ESMTPS id 278836E8CA for ; Fri, 27 Apr 2018 11:31:50 +0000 (UTC) Received: from localhost.localdomain (unknown [IPv6:2a02:8109:9280:1d42:c0a8:9d3a:83aa:3d49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: robertfoss) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id 70D68276CFB; Fri, 27 Apr 2018 12:31:48 +0100 (BST) From: Robert Foss To: dri-devel , John Stultz , Emil Velikov , Tomasz Figa , Stefan Schake , Chih-Wei Huang Subject: [PATCH v1] xf86drm: Add drmHandleMatch func Date: Fri, 27 Apr 2018 13:31:17 +0200 Message-Id: <20180427113117.19066-1-robert.foss@collabora.com> X-Mailer: git-send-email 2.14.1 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Robert Foss , Tomeu Vizoso , Daniel Stone MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP drmHandleMatch is intended to allow for userspace to filter out devices that it does not want to open. Opening specific devices using paths alone is not a reliable due to probing order. This function intends to provide a mechanism for filtering out devices that don't fit what you need using an extensible set of filters. drm_match_key_t is intended to be extended with whatever filter that would come in handy down the line. As a catch-all filter, the DRM_MATCH_FUNCTION was included which allows the caller to filter based on an arbitrary function. An function pointer filter could of course filter based on anything. But for the sake of convenience a few other simple filters have been included. If the function pointer filter ends up being called with a boilerplate fp by mutliple libdrm users, perhaps that funtion could be moved into libdrm at a future date. Signed-off-by: Robert Foss --- This patch implements a simple function for matching DRM device FDs against the desired properties of a device that you are looking for. The discussion that led to this series can be found here: https://lists.freedesktop.org/archives/mesa-dev/2018-January/183878.html The RFC can be found here: https://www.spinics.net/lists/dri-devel/msg172398.html Since the RFC I opted to rework the patch to be more extensible. The previous implementation would have been problematic if the drmVersion or drmDevice structs ever needed to be changed or removed. Or indeed if more properties were to become interesting. As it is now, it is basially implemented as per Daniel Stones suggestion in the RFC discussion. Changes since RFC: - Reworked proposal to be not be based on structs in order to be more flexible. - Now uses filters of different types. - Caller can supply any number of predefined and function pointer filter. xf86drm.h | 24 ++++++++++++++++++++ xf86drmMode.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/xf86drm.h b/xf86drm.h index 7773d71a8030..71bf39baf9b2 100644 --- a/xf86drm.h +++ b/xf86drm.h @@ -863,6 +863,30 @@ extern int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_device extern int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b); +typedef enum drm_match_key { + /* Match against DRM_NODE_{PRIMARY,RENDER,...} type */ + DRM_MATCH_NODE_TYPE = 1, + DRM_MATCH_DRIVER_NAME = 2, + DRM_MATCH_BUS_PCI_VENDOR = 3, + DRM_MATCH_FUNCTION = 4, +} drm_match_key_t; + +typedef struct drm_match_func { + void *data; + int (*fp)(int, void*); /* Intended arguments are fp(fd, data) */ +} drm_match_func_t; + +typedef struct drm_match { + drm_match_key_t type; + union { + int s; + uint16_t u16; + char *str; + drm_match_func_t func; + }; +} drm_match_t; +extern int drmHandleMatch(int fd, drm_match_t *filters, int nbr_filters); + extern int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle); extern int drmSyncobjDestroy(int fd, uint32_t handle); extern int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd); diff --git a/xf86drmMode.c b/xf86drmMode.c index 9a15b5e78dda..28446e7d4ac6 100644 --- a/xf86drmMode.c +++ b/xf86drmMode.c @@ -946,6 +946,76 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx) return 0; } +int drmHandleMatch(int fd, drm_match_t *filters, int nbr_filters) +{ + if (fd < 0) + goto error; + + if (nbr_filters > 0 && filters == NULL) + goto error; + + drmVersionPtr ver = drmGetVersion(fd); + if (!ver) + goto fail; + + drmDevicePtr dev = NULL; + if (drmGetDevice2(fd, 0, &dev) != 0) { + goto fail; + } + + for (int i = 0; i < nbr_filters; i++) { + drm_match_t *f = &filters[i]; + switch (f->type) { + case DRM_MATCH_NODE_TYPE: + if (!(dev->available_nodes & (1 << f->s))) + goto fail; + break; + case DRM_MATCH_DRIVER_NAME: + if (!f->str) + goto error; + + /* This bypass is used by when the driver name is used + by the Android property_get() func, when it hasn't found + the property and the string is empty as a result. */ + if (strlen(f->str) == 0) + continue; + + if (strncmp(ver->name, f->str, strlen(ver->name))) + goto fail; + break; + case DRM_MATCH_BUS_PCI_VENDOR: + if (dev->bustype != DRM_BUS_PCI) + goto fail; + if (dev->deviceinfo.pci->vendor_id != f->u16) + goto fail; + break; + case DRM_MATCH_FUNCTION: + if (!f->func.fp) + goto error; + int (*fp)(int, void*) = f->func.fp; + void *data = f->func.data; + if (!fp(fd, data)) + goto fail; + break; + default: + goto error; + } + } + +success: + drmFreeVersion(ver); + drmFreeDevice(&dev); + return 0; +error: + drmFreeVersion(ver); + drmFreeDevice(&dev); + return -EINVAL; +fail: + drmFreeVersion(ver); + drmFreeDevice(&dev); + return 1; +} + int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, uint32_t flags, void *user_data) {