/* * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #pragma once #include_next #include #include /* * FIXME: Below code comes from https://patchwork.kernel.org/patch/10368203/ * FIXME: Remove or rework once that has been merged */ 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; static inline 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; }