2 * Copyright © 2019 Red Hat
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 #include <wayland-client.h>
25 #include "wayland-drm-client-protocol.h"
26 #include "device_select.h"
32 struct device_select_wayland_info
{
33 struct wl_drm
*wl_drm
;
34 drmDevicePtr dev_info
;
39 device_select_drm_handle_device(void *data
, struct wl_drm
*drm
, const char *device
)
41 struct device_select_wayland_info
*info
= data
;
43 int fd
= open(device
, O_RDWR
| O_CLOEXEC
);
47 int ret
= drmGetDevice2(fd
, 0, &info
->dev_info
);
49 info
->info_is_set
= true;
55 device_select_drm_handle_format(void *data
, struct wl_drm
*drm
, uint32_t format
)
61 device_select_drm_handle_authenticated(void *data
, struct wl_drm
*drm
)
68 device_select_drm_handle_capabilities(void *data
, struct wl_drm
*drm
, uint32_t value
)
74 static const struct wl_drm_listener ds_drm_listener
= {
75 .device
= device_select_drm_handle_device
,
76 .format
= device_select_drm_handle_format
,
77 .authenticated
= device_select_drm_handle_authenticated
,
78 .capabilities
= device_select_drm_handle_capabilities
82 device_select_registry_global(void *data
, struct wl_registry
*registry
, uint32_t name
,
83 const char *interface
, uint32_t version
)
85 struct device_select_wayland_info
*info
= data
;
86 if (strcmp(interface
, "wl_drm") == 0) {
87 info
->wl_drm
= wl_registry_bind(registry
, name
, &wl_drm_interface
, MIN2(version
, 2));
88 wl_drm_add_listener(info
->wl_drm
, &ds_drm_listener
, data
);
93 device_select_registry_global_remove_cb(void *data
, struct wl_registry
*registry
,
99 int device_select_find_wayland_pci_default(struct device_pci_info
*devices
, uint32_t device_count
)
101 struct wl_display
*display
;
102 struct wl_registry
*registry
= NULL
;
103 unsigned default_idx
= -1;
104 struct device_select_wayland_info info
= {};
106 display
= wl_display_connect(NULL
);
110 registry
= wl_display_get_registry(display
);
112 wl_display_disconnect(display
);
116 static const struct wl_registry_listener registry_listener
=
117 { device_select_registry_global
, device_select_registry_global_remove_cb
};
119 wl_registry_add_listener(registry
, ®istry_listener
, &info
);
120 wl_display_dispatch(display
);
121 wl_display_roundtrip(display
);
124 if (info
.info_is_set
) {
125 for (unsigned i
= 0; i
< device_count
; i
++) {
126 if (devices
[i
].has_bus_info
) {
127 if (info
.dev_info
->businfo
.pci
->domain
== devices
[i
].bus_info
.domain
&&
128 info
.dev_info
->businfo
.pci
->bus
== devices
[i
].bus_info
.bus
&&
129 info
.dev_info
->businfo
.pci
->dev
== devices
[i
].bus_info
.dev
&&
130 info
.dev_info
->businfo
.pci
->func
== devices
[i
].bus_info
.func
)
133 if (info
.dev_info
->deviceinfo
.pci
->vendor_id
== devices
[i
].dev_info
.vendor_id
&&
134 info
.dev_info
->deviceinfo
.pci
->device_id
== devices
[i
].dev_info
.device_id
)
137 if (default_idx
!= -1)
142 wl_drm_destroy(info
.wl_drm
);
143 wl_registry_destroy(registry
);
144 wl_display_disconnect(display
);