[PATCH libdrm v3 2/5] xf86drm: Add USB support
walter harms
wharms at bfs.de
Wed Jan 18 11:21:23 UTC 2017
Am 18.01.2017 10:02, schrieb Thierry Reding:
> 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 at 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;
char *filename=NULL, *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);
since asprintf() is available you could use:
asprintf(&filename,"%s/uevent", path);
same could be done for path below.
> +
> + fp = fopen(filename, "r");
> + if (!fp)
goto release_mem;
> +
> + 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);
> +
release_mem:
free(filename);
> + free(key);
> +
> + return value;
> +}
> +#endif
just my 2 cents
re,
wh
> +
> 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;
>
More information about the xorg-devel
mailing list