1 /*
2 * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #define _GNU_SOURCE 1
26 #include "sysdeps.h"
27 #include <dlfcn.h>
28 #include <X11/Xlib.h>
29 #include "va_drm_auth_x11.h"
30
31 typedef struct drm_auth_x11 DRMAuthX11;
32 typedef struct drm_auth_x11_vtable DRMAuthX11VTable;
33
34 typedef void (*VAGenericFunc)(void);
35 typedef Display *(*X11OpenDisplayFunc)(const char *display_name);
36 typedef int (*X11CloseDisplayFunc)(Display *display);
37 typedef Bool(*VADRI2AuthenticateFunc)(
38 Display *display, XID window, uint32_t magic);
39
40 struct drm_auth_x11_vtable {
41 X11OpenDisplayFunc x11_open_display;
42 X11CloseDisplayFunc x11_close_display;
43 VADRI2AuthenticateFunc va_dri2_authenticate;
44 };
45
46 struct drm_auth_x11 {
47 void *handle; /* libva-x11.so.1 */
48 DRMAuthX11VTable vtable;
49 Display *display;
50 Window window;
51 };
52
53 static bool
get_symbol(void * handle,void * func_vptr,const char * name)54 get_symbol(void *handle, void *func_vptr, const char *name)
55 {
56 VAGenericFunc func, *func_ptr = func_vptr;
57 const char *error;
58
59 dlerror();
60 func = (VAGenericFunc)dlsym(handle, name);
61 error = dlerror();
62
63 if (error) {
64 fprintf(stderr, "error: failed to resolve %s() function: %s\n",
65 name, error);
66 return false;
67 }
68
69 *func_ptr = func;
70 return true;
71 }
72
73 static bool
drm_auth_x11_init(DRMAuthX11 * auth)74 drm_auth_x11_init(DRMAuthX11 *auth)
75 {
76 struct drm_auth_x11_vtable *vtable;
77 char libva_x11_name[16];
78 int ret;
79
80 ret = snprintf(
81 libva_x11_name, sizeof(libva_x11_name),
82 "libva-x11.so.%d", LIBVA_MAJOR_VERSION
83 );
84 if (ret < 0 || ret >= sizeof(libva_x11_name))
85 return false;
86
87 auth->handle = dlopen(libva_x11_name, RTLD_LAZY | RTLD_GLOBAL);
88 if (!auth->handle) {
89 perror("open lib");
90 return false;
91 }
92
93 vtable = &auth->vtable;
94 if (!get_symbol(RTLD_DEFAULT, &vtable->x11_open_display, "XOpenDisplay"))
95 return false;
96 if (!get_symbol(RTLD_DEFAULT, &vtable->x11_close_display, "XCloseDisplay"))
97 return false;
98 if (!get_symbol(auth->handle, &vtable->va_dri2_authenticate,
99 "VA_DRI2Authenticate"))
100 return false;
101
102 auth->display = vtable->x11_open_display(NULL);
103 if (!auth->display)
104 return false;
105
106 auth->window = DefaultRootWindow(auth->display);
107 return true;
108 }
109
110 static void
drm_auth_x11_terminate(DRMAuthX11 * auth)111 drm_auth_x11_terminate(DRMAuthX11 *auth)
112 {
113 if (!auth)
114 return;
115
116 if (auth->display) {
117 auth->vtable.x11_close_display(auth->display);
118 auth->display = NULL;
119 auth->window = None;
120 }
121
122 if (auth->handle) {
123 dlclose(auth->handle);
124 auth->handle = NULL;
125 }
126 }
127
128 /* Try to authenticate the DRM connection with the supplied magic through X11 */
129 bool
va_drm_authenticate_x11(int fd,uint32_t magic)130 va_drm_authenticate_x11(int fd, uint32_t magic)
131 {
132 DRMAuthX11VTable * vtable;
133 DRMAuthX11 auth;
134 bool success = false;
135
136 memset(&auth, 0, sizeof(auth));
137 if (!drm_auth_x11_init(&auth))
138 goto end;
139 vtable = &auth.vtable;
140 success = vtable->va_dri2_authenticate(auth.display, auth.window, magic);
141
142 end:
143 drm_auth_x11_terminate(&auth);
144 return success;
145 }
146