[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