Message ID | 20161110174305.31525-1-emil.l.velikov@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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); >
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 --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);