#endif
#include <math.h>
+#if defined(__FreeBSD__)
+#include <sys/param.h>
+#endif
+
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
/* Not all systems have MAP_FAILED defined */
snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/drm",
maj, min);
return stat(path, &sbuf) == 0;
+#elif __FreeBSD__
+ char name[SPECNAMELEN];
+
+ if (!devname_r(makedev(maj, min), S_IFCHR, name, sizeof(name)))
+ return 0;
+ /* Handle drm/ and dri/ as both are present in different FreeBSD version
+ * FreeBSD on amd64/i386/powerpc external kernel modules create node in
+ * in /dev/drm/ and links in /dev/dri while a WIP in kernel driver creates
+ * only device nodes in /dev/dri/ */
+ return (!strncmp(name, "drm/", 4) || !strncmp(name, "dri/", 4));
#else
return maj == DRM_MAJOR;
#endif
/* Little white lie to avoid major rework of the existing code */
#define DRM_BUS_VIRTIO 0x10
-static int drmParseSubsystemType(int maj, int min)
-{
#ifdef __linux__
- char path[PATH_MAX + 1];
+static int get_subsystem_type(const char *device_path)
+{
+ char path[PATH_MAX + 1] = "";
char link[PATH_MAX + 1] = "";
char *name;
struct {
{ "/virtio", DRM_BUS_VIRTIO },
};
- snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/subsystem",
- maj, min);
+ strncpy(path, device_path, PATH_MAX);
+ strncat(path, "/subsystem", PATH_MAX);
if (readlink(path, link, PATH_MAX) < 0)
return -errno;
}
return -EINVAL;
+}
+#endif
+
+static int drmParseSubsystemType(int maj, int min)
+{
+#ifdef __linux__
+ char path[PATH_MAX + 1] = "";
+ char real_path[PATH_MAX + 1] = "";
+ int subsystem_type;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+ if (!realpath(path, real_path))
+ return -errno;
+ snprintf(path, sizeof(path), "%s", real_path);
+
+ subsystem_type = get_subsystem_type(path);
+ if (subsystem_type == DRM_BUS_VIRTIO) {
+ strncat(path, "/..", PATH_MAX);
+ subsystem_type = get_subsystem_type(path);
+ }
+ return subsystem_type;
#elif defined(__OpenBSD__) || defined(__DragonFly__)
return DRM_BUS_PCI;
#else
switch (subsystem_type) {
case DRM_BUS_PCI:
- case DRM_BUS_VIRTIO:
return drmProcessPciDevice(device, node, node_type, maj, min,
fetch_deviceinfo, flags);
case DRM_BUS_USB: