• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
3  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  */
25 
26 #pragma once
27 
28 #include_next <xf86drm.h>
29 
30 #include <string.h>
31 #include <errno.h>
32 
33 /*
34  * FIXME: Below code comes from https://patchwork.kernel.org/patch/10368203/
35  * FIXME: Remove or rework once that has been merged
36  */
37 
38 typedef enum drm_match_key {
39 	/* Match against DRM_NODE_{PRIMARY,RENDER,...} type */
40 	DRM_MATCH_NODE_TYPE = 1,
41 	DRM_MATCH_DRIVER_NAME = 2,
42 	DRM_MATCH_BUS_PCI_VENDOR = 3,
43 	DRM_MATCH_FUNCTION = 4,
44 } drm_match_key_t;
45 
46 typedef struct drm_match_func {
47 	void *data;
48 	int (*fp)(int, void*); /* Intended arguments are fp(fd, data) */
49 } drm_match_func_t;
50 
51 typedef struct drm_match {
52 	drm_match_key_t type;
53 	union {
54 		int s;
55 		uint16_t u16;
56 		char *str;
57 		drm_match_func_t func;
58 	};
59 } drm_match_t;
60 
drmHandleMatch(int fd,drm_match_t * filters,int nbr_filters)61 static inline int drmHandleMatch(int fd, drm_match_t *filters, int nbr_filters)
62 {
63 	if (fd < 0)
64 		goto error;
65 
66 	if (nbr_filters > 0 && filters == NULL)
67 		goto error;
68 
69 	drmVersionPtr ver = drmGetVersion(fd);
70 	if (!ver)
71 		goto fail;
72 
73 	drmDevicePtr dev = NULL;
74 	if (drmGetDevice2(fd, 0, &dev) != 0) {
75 		goto fail;
76 	}
77 
78 	for (int i = 0; i < nbr_filters; i++) {
79 		drm_match_t *f = &filters[i];
80 		switch (f->type) {
81 		case DRM_MATCH_NODE_TYPE:
82 			if (!(dev->available_nodes & (1 << f->s)))
83 				goto fail;
84 			break;
85 		case DRM_MATCH_DRIVER_NAME:
86 			if (!f->str)
87 				goto error;
88 
89 			/* This bypass is used by when the driver name is used
90 			   by the Android property_get() func, when it hasn't found
91 			   the property and the string is empty as a result. */
92 			if (strlen(f->str) == 0)
93 				continue;
94 
95 			if (strncmp(ver->name, f->str, strlen(ver->name)))
96 				goto fail;
97 			break;
98 		case DRM_MATCH_BUS_PCI_VENDOR:
99 			if (dev->bustype != DRM_BUS_PCI)
100 				goto fail;
101 			if (dev->deviceinfo.pci->vendor_id != f->u16)
102 				goto fail;
103 			break;
104 		case DRM_MATCH_FUNCTION:
105 			if (!f->func.fp)
106 				goto error;
107 			int (*fp)(int, void*) = f->func.fp;
108 			void *data = f->func.data;
109 			if (!fp(fd, data))
110 				goto fail;
111 			break;
112 		default:
113 			goto error;
114 		}
115 	}
116 
117 success:
118 	drmFreeVersion(ver);
119 	drmFreeDevice(&dev);
120 	return 0;
121 error:
122 	drmFreeVersion(ver);
123 	drmFreeDevice(&dev);
124 	return -EINVAL;
125 fail:
126 	drmFreeVersion(ver);
127 	drmFreeDevice(&dev);
128 	return 1;
129 }
130 
131