From: Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Cc: xorg-devel-go0+a7rfsptAfugRpC6u6w@public.gmane.org,
Thierry Reding
<thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
Emil Velikov
<emil.l.velikov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Subject: [PATCH libdrm v3 2/5] xf86drm: Add USB support
Date: Wed, 18 Jan 2017 10:02:06 +0100 [thread overview]
Message-ID: <20170118090209.13819-3-thierry.reding@gmail.com> (raw)
In-Reply-To: <20170118090209.13819-1-thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Allow DRM/KMS devices hosted on USB to be detected by the drmDevice
infrastructure.
v3:
- guard Linux-specific sysfs parsing code with #ifdef __linux__
v2:
- make sysfs_uevent_get() more flexible using a format string
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
---
xf86drm.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
xf86drm.h | 13 +++++
2 files changed, 188 insertions(+)
diff --git a/xf86drm.c b/xf86drm.c
index 7766bfe937db..d83674e638c4 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -2886,6 +2886,50 @@ char *drmGetRenderDeviceNameFromFd(int fd)
return drmGetMinorNameForFD(fd, DRM_NODE_RENDER);
}
+#ifdef __linux__
+static char * DRM_PRINTFLIKE(2, 3)
+sysfs_uevent_get(const char *path, const char *fmt, ...)
+{
+ char filename[PATH_MAX + 1], *key, *line = NULL, *value = NULL;
+ size_t size = 0, len;
+ ssize_t num;
+ va_list ap;
+ FILE *fp;
+
+ va_start(ap, fmt);
+ num = vasprintf(&key, fmt, ap);
+ va_end(ap);
+ len = num;
+
+ snprintf(filename, sizeof(filename), "%s/uevent", path);
+
+ fp = fopen(filename, "r");
+ if (!fp) {
+ free(key);
+ return NULL;
+ }
+
+ while ((num = getline(&line, &size, fp)) >= 0) {
+ if ((strncmp(line, key, len) == 0) && (line[len] == '=')) {
+ char *start = line + len + 1, *end = line + num - 1;
+
+ if (*end != '\n')
+ end++;
+
+ value = strndup(start, end - start);
+ break;
+ }
+ }
+
+ free(line);
+ fclose(fp);
+
+ free(key);
+
+ return value;
+}
+#endif
+
static int drmParseSubsystemType(int maj, int min)
{
#ifdef __linux__
@@ -2906,6 +2950,9 @@ static int drmParseSubsystemType(int maj, int min)
if (strncmp(name, "/pci", 4) == 0)
return DRM_BUS_PCI;
+ if (strncmp(name, "/usb", 4) == 0)
+ return DRM_BUS_USB;
+
return -EINVAL;
#elif defined(__OpenBSD__)
return DRM_BUS_PCI;
@@ -2992,6 +3039,10 @@ static int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b)
switch (a->bustype) {
case DRM_BUS_PCI:
return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo));
+
+ case DRM_BUS_USB:
+ return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo));
+
default:
break;
}
@@ -3235,6 +3286,113 @@ free_device:
return ret;
}
+static int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info)
+{
+#ifdef __linux__
+ char path[PATH_MAX + 1], *value;
+ unsigned int bus, dev;
+ int ret;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+
+ value = sysfs_uevent_get(path, "BUSNUM");
+ if (!value)
+ return -ENOENT;
+
+ ret = sscanf(value, "%03u", &bus);
+ free(value);
+
+ if (ret <= 0)
+ return -errno;
+
+ value = sysfs_uevent_get(path, "DEVNUM");
+ if (!value)
+ return -ENOENT;
+
+ ret = sscanf(value, "%03u", &dev);
+ free(value);
+
+ if (ret <= 0)
+ return -errno;
+
+ info->bus = bus;
+ info->dev = dev;
+
+ return 0;
+#else
+#warning "Missing implementation of drmParseUsbBusInfo"
+ return -EINVAL;
+#endif
+}
+
+static int drmParseUsbDeviceInfo(int maj, int min, drmUsbDeviceInfoPtr info)
+{
+#ifdef __linux__
+ char path[PATH_MAX + 1], *value;
+ unsigned int vendor, product;
+ int ret;
+
+ snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+
+ value = sysfs_uevent_get(path, "PRODUCT");
+ if (!value)
+ return -ENOENT;
+
+ ret = sscanf(value, "%x/%x", &vendor, &product);
+ free(value);
+
+ if (ret <= 0)
+ return -errno;
+
+ info->vendor = vendor;
+ info->product = product;
+
+ return 0;
+#else
+#warning "Missing implementation of drmParseUsbDeviceInfo"
+ return -EINVAL;
+#endif
+}
+
+static int drmProcessUsbDevice(drmDevicePtr *device, const char *node,
+ int node_type, int maj, int min,
+ bool fetch_deviceinfo, uint32_t flags)
+{
+ drmDevicePtr dev;
+ char *ptr;
+ int ret;
+
+ dev = drmDeviceAlloc(node_type, node, sizeof(drmUsbBusInfo),
+ sizeof(drmUsbDeviceInfo), &ptr);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->bustype = DRM_BUS_USB;
+
+ dev->businfo.usb = (drmUsbBusInfoPtr)ptr;
+
+ ret = drmParseUsbBusInfo(maj, min, dev->businfo.usb);
+ if (ret < 0)
+ goto free_device;
+
+ if (fetch_deviceinfo) {
+ ptr += sizeof(drmUsbBusInfo);
+ dev->deviceinfo.usb = (drmUsbDeviceInfoPtr)ptr;
+
+ ret = drmParseUsbDeviceInfo(maj, min, dev->deviceinfo.usb);
+ if (ret < 0)
+ goto free_device;
+ }
+
+ *device = dev;
+
+ return 0;
+
+free_device:
+ free(dev);
+ return ret;
+}
+
/* Consider devices located on the same bus as duplicate and fold the respective
* entries into a single one.
*
@@ -3410,6 +3568,14 @@ int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
continue;
break;
+
+ case DRM_BUS_USB:
+ ret = drmProcessUsbDevice(&d, node, node_type, maj, min, true, flags);
+ if (ret)
+ goto free_devices;
+
+ break;
+
default:
continue;
}
@@ -3541,6 +3707,15 @@ int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices)
continue;
break;
+
+ case DRM_BUS_USB:
+ ret = drmProcessUsbDevice(&device, node, node_type, maj, min,
+ devices != NULL, flags);
+ if (ret)
+ goto free_devices;
+
+ break;
+
default:
continue;
}
diff --git a/xf86drm.h b/xf86drm.h
index b340fc46cd44..65d5321950fc 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -767,6 +767,7 @@ extern char *drmGetPrimaryDeviceNameFromFd(int fd);
extern char *drmGetRenderDeviceNameFromFd(int fd);
#define DRM_BUS_PCI 0
+#define DRM_BUS_USB 1
typedef struct _drmPciBusInfo {
uint16_t domain;
@@ -783,15 +784,27 @@ typedef struct _drmPciDeviceInfo {
uint8_t revision_id;
} drmPciDeviceInfo, *drmPciDeviceInfoPtr;
+typedef struct _drmUsbBusInfo {
+ uint8_t bus;
+ uint8_t dev;
+} drmUsbBusInfo, *drmUsbBusInfoPtr;
+
+typedef struct _drmUsbDeviceInfo {
+ uint16_t vendor;
+ uint16_t product;
+} drmUsbDeviceInfo, *drmUsbDeviceInfoPtr;
+
typedef struct _drmDevice {
char **nodes; /* DRM_NODE_MAX sized array */
int available_nodes; /* DRM_NODE_* bitmask */
int bustype;
union {
drmPciBusInfoPtr pci;
+ drmUsbBusInfoPtr usb;
} businfo;
union {
drmPciDeviceInfoPtr pci;
+ drmUsbDeviceInfoPtr usb;
} deviceinfo;
} drmDevice, *drmDevicePtr;
--
2.11.0
_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel
next prev parent reply other threads:[~2017-01-18 9:02 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-18 9:02 [PATCH libdrm v3 0/5] xf86drm: Add USB, platform and host1x bus support Thierry Reding
2017-01-18 9:02 ` [PATCH libdrm v3 1/5] xf86drm: Factor out drmDeviceAlloc() Thierry Reding
[not found] ` <20170118090209.13819-1-thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-01-18 9:02 ` Thierry Reding [this message]
[not found] ` <587F4FB3.2070006@bfs.de>
2017-01-19 10:20 ` [PATCH libdrm v3 2/5] xf86drm: Add USB support Thierry Reding
[not found] ` <20170119102038.GB30182-EkSeR96xj6Pcmrwk2tT4+A@public.gmane.org>
2017-01-21 17:44 ` walter harms
2017-01-18 9:02 ` [PATCH libdrm v3 3/5] xf86drm: Add platform and host1x bus support Thierry Reding
[not found] ` <587F8304.90105@bfs.de>
2017-01-19 10:25 ` Thierry Reding
[not found] ` <20170118090209.13819-4-thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-01-20 14:03 ` Emil Velikov
2017-01-18 9:02 ` [PATCH libdrm v3 4/5] tests/drmdevice: Add USB, platform and host1x support Thierry Reding
2017-01-18 9:02 ` [PATCH libdrm v3 5/5] xf86drm: Reuse sysfs_uevent_get() Thierry Reding
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170118090209.13819-3-thierry.reding@gmail.com \
--to=thierry.reding-re5jqeeqqe8avxtiumwx3w@public.gmane.org \
--cc=dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
--cc=emil.l.velikov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=xorg-devel-go0+a7rfsptAfugRpC6u6w@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.