diff mbox

[libdrm] xf86drm: introduce drmGetDeviceNameFromFd2

Message ID 20161110174305.31525-1-emil.l.velikov@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Emil Velikov Nov. 10, 2016, 5:43 p.m. UTC
From: Emil Velikov <emil.velikov@collabora.com>

The original version considered only card devices, while this will pick
the device/node name regardless - card, control, renderD, other...

Current implementation is "linux" specific, in such that it relies on
sysfs/uevent file. At the same time this gives us the flexibility to
support any nodes even future ones, as long as they're within DRM_MAJOR.

Shamelessly copied from mesa, latter by: Gary Wong <gtw@gnu.org>
Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
---
There's quite a bit of [subtle chaos] in mesa about this. Sometimes we
explicitly request the render node, sometimes we use an open-coded version
of drmGetDeviceNameFromFd, which due to sheer luck just works.

One could apply some polish here, but I'd choose to keep things as close
to original.
---
 xf86drm.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 xf86drm.h |  5 +++++
 2 files changed, 56 insertions(+)

Comments

Nicolai Hähnle Nov. 16, 2016, 11:14 a.m. UTC | #1
On 10.11.2016 18:43, Emil Velikov wrote:
> From: Emil Velikov <emil.velikov@collabora.com>
>
> The original version considered only card devices, while this will pick
> the device/node name regardless - card, control, renderD, other...
>
> Current implementation is "linux" specific, in such that it relies on
> sysfs/uevent file. At the same time this gives us the flexibility to
> support any nodes even future ones, as long as they're within DRM_MAJOR.
>
> Shamelessly copied from mesa, latter by: Gary Wong <gtw@gnu.org>
> Signed-off-by: Emil Velikov <emil.velikov@collabora.com>

Makes sense to me.

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>

> ---
> There's quite a bit of [subtle chaos] in mesa about this. Sometimes we
> explicitly request the render node, sometimes we use an open-coded version
> of drmGetDeviceNameFromFd, which due to sheer luck just works.
>
> One could apply some polish here, but I'd choose to keep things as close
> to original.
> ---
>  xf86drm.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  xf86drm.h |  5 +++++
>  2 files changed, 56 insertions(+)
>
> diff --git a/xf86drm.c b/xf86drm.c
> index 80e2f27..0bca43a 100644
> --- a/xf86drm.c
> +++ b/xf86drm.c
> @@ -3367,3 +3367,54 @@ free_locals:
>      free(local_devices);
>      return ret;
>  }
> +
> +char *drmGetDeviceNameFromFd2(int fd)
> +{
> +#ifdef __linux__
> +    struct stat sbuf;
> +    char *device_name = NULL;
> +    unsigned int maj, min;
> +    FILE *f;
> +    char buf[512];
> +    static const char match[9] = "\nDEVNAME=";
> +    int expected = 1;
> +
> +
> +    if (fstat(fd, &sbuf))
> +        return NULL;
> +
> +    maj = major(sbuf.st_rdev);
> +    min = minor(sbuf.st_rdev);
> +
> +    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
> +        return NULL;
> +
> +    snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/uevent", maj, min);
> +    if (!(f = fopen(buf, "r")))
> +        return NULL;
> +
> +    while (expected < sizeof(match)) {
> +        int c = getc(f);
> +
> +        if (c == EOF) {
> +            fclose(f);
> +            return NULL;
> +        } else if (c == match[expected] )
> +            expected++;
> +        else
> +            expected = 0;
> +    }
> +
> +    strcpy(buf, "/dev/");
> +    if (fgets(buf + 5, sizeof(buf) - 5, f)) {
> +        buf[strcspn(buf, "\n")] = '\0';
> +        device_name = strdup(buf);
> +    }
> +
> +    fclose(f);
> +    return device_name;
> +#else
> +#warning "Missing implementation of drmGetDeviceNameFromFd2"
> +    return NULL;
> +#endif
> +}
> diff --git a/xf86drm.h b/xf86drm.h
> index d1ebc32..4fa395e 100644
> --- a/xf86drm.h
> +++ b/xf86drm.h
> @@ -753,6 +753,11 @@ typedef struct _drmEventContext {
>  extern int drmHandleEvent(int fd, drmEventContextPtr evctx);
>
>  extern char *drmGetDeviceNameFromFd(int fd);
> +
> +/* Improved version of drmGetDeviceNameFromFd which attributes for any type of
> + * device/node - card, control or renderD.
> + */
> +extern char *drmGetDeviceNameFromFd2(int fd);
>  extern int drmGetNodeTypeFromFd(int fd);
>
>  extern int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd);
>
Emil Velikov Nov. 22, 2016, 2:24 p.m. UTC | #2
On 16 November 2016 at 11:14, Nicolai Hähnle <nhaehnle@gmail.com> wrote:
> On 10.11.2016 18:43, Emil Velikov wrote:
>>
>> From: Emil Velikov <emil.velikov@collabora.com>
>>
>> The original version considered only card devices, while this will pick
>> the device/node name regardless - card, control, renderD, other...
>>
>> Current implementation is "linux" specific, in such that it relies on
>> sysfs/uevent file. At the same time this gives us the flexibility to
>> support any nodes even future ones, as long as they're within DRM_MAJOR.
>>
>> Shamelessly copied from mesa, latter by: Gary Wong <gtw@gnu.org>
>> Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
>
>
> Makes sense to me.
>
> Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
>
Great, ty.
Next step - the revision (-less) patches. Since the kernel thread
reached conclusion :-)

-Emil
diff mbox

Patch

diff --git a/xf86drm.c b/xf86drm.c
index 80e2f27..0bca43a 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -3367,3 +3367,54 @@  free_locals:
     free(local_devices);
     return ret;
 }
+
+char *drmGetDeviceNameFromFd2(int fd)
+{
+#ifdef __linux__
+    struct stat sbuf;
+    char *device_name = NULL;
+    unsigned int maj, min;
+    FILE *f;
+    char buf[512];
+    static const char match[9] = "\nDEVNAME=";
+    int expected = 1;
+
+
+    if (fstat(fd, &sbuf))
+        return NULL;
+
+    maj = major(sbuf.st_rdev);
+    min = minor(sbuf.st_rdev);
+
+    if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+        return NULL;
+
+    snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/uevent", maj, min);
+    if (!(f = fopen(buf, "r")))
+        return NULL;
+
+    while (expected < sizeof(match)) {
+        int c = getc(f);
+
+        if (c == EOF) {
+            fclose(f);
+            return NULL;
+        } else if (c == match[expected] )
+            expected++;
+        else
+            expected = 0;
+    }
+
+    strcpy(buf, "/dev/");
+    if (fgets(buf + 5, sizeof(buf) - 5, f)) {
+        buf[strcspn(buf, "\n")] = '\0';
+        device_name = strdup(buf);
+    }
+
+    fclose(f);
+    return device_name;
+#else
+#warning "Missing implementation of drmGetDeviceNameFromFd2"
+    return NULL;
+#endif
+}
diff --git a/xf86drm.h b/xf86drm.h
index d1ebc32..4fa395e 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -753,6 +753,11 @@  typedef struct _drmEventContext {
 extern int drmHandleEvent(int fd, drmEventContextPtr evctx);
 
 extern char *drmGetDeviceNameFromFd(int fd);
+
+/* Improved version of drmGetDeviceNameFromFd which attributes for any type of
+ * device/node - card, control or renderD.
+ */
+extern char *drmGetDeviceNameFromFd2(int fd);
 extern int drmGetNodeTypeFromFd(int fd);
 
 extern int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd);