OSDN Git Service

android: set LOCAL_MODULE_TAGS to optional
[android-x86/external-libdrm.git] / xf86drmMode.c
index 44ef05b..c94e40c 100644 (file)
 #define U642VOID(x) ((void *)(unsigned long)(x))
 #define VOID2U64(x) ((uint64_t)(unsigned long)(x))
 
+static inline int DRM_IOCTL(int fd, int cmd, void *arg)
+{
+       int ret = drmIoctl(fd, cmd, arg);
+       return ret < 0 ? -errno : ret;
+}
+
 /*
  * Util functions
  */
@@ -206,7 +212,11 @@ retry:
        r->crtcs      = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t));
        r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t));
        r->encoders   = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t));
-       if (!r->fbs || !r->crtcs || !r->connectors || !r->encoders) {
+       if ((res.count_fbs && !r->fbs) ||
+           (res.count_crtcs && !r->crtcs) ||
+           (res.count_connectors && !r->connectors) ||
+           (res.count_encoders && !r->encoders))
+       {
                drmFree(r->fbs);
                drmFree(r->crtcs);
                drmFree(r->connectors);
@@ -238,7 +248,7 @@ int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
        f.depth  = depth;
        f.handle = bo_handle;
 
-       if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB, &f)))
+       if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f)))
                return ret;
 
        *buf_id = f.fb_id;
@@ -247,7 +257,7 @@ int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
 
 int drmModeRmFB(int fd, uint32_t bufferId)
 {
-       return drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
+       return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
 
 
 }
@@ -285,7 +295,7 @@ int drmModeDirtyFB(int fd, uint32_t bufferId,
        dirty.clips_ptr = VOID2U64(clips);
        dirty.num_clips = num_clips;
 
-       return drmIoctl(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty);
+       return DRM_IOCTL(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty);
 }
 
 
@@ -340,7 +350,7 @@ int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
        } else
          crtc.mode_valid = 0;
 
-       return drmIoctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
+       return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
 }
 
 /*
@@ -357,7 +367,7 @@ int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width
        arg.height = height;
        arg.handle = bo_handle;
 
-       return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
+       return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg);
 }
 
 int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
@@ -369,7 +379,7 @@ int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
        arg.x = x;
        arg.y = y;
 
-       return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
+       return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg);
 }
 
 /*
@@ -406,37 +416,57 @@ drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
 
 drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
 {
-       struct drm_mode_get_connector conn;
+       struct drm_mode_get_connector conn, counts;
        drmModeConnectorPtr r = NULL;
 
+retry:
+       memset(&conn, 0, sizeof(struct drm_mode_get_connector));
        conn.connector_id = connector_id;
-       conn.connector_type_id = 0;
-       conn.connector_type  = 0;
-       conn.count_modes  = 0;
-       conn.modes_ptr    = 0;
-       conn.count_props  = 0;
-       conn.props_ptr    = 0;
-       conn.prop_values_ptr = 0;
-       conn.count_encoders  = 0;
-       conn.encoders_ptr = 0;
 
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
                return 0;
 
+       counts = conn;
+
        if (conn.count_props) {
                conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
+               if (!conn.props_ptr)
+                       goto err_allocs;
                conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
+               if (!conn.prop_values_ptr)
+                       goto err_allocs;
        }
 
-       if (conn.count_modes)
+       if (conn.count_modes) {
                conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));
+               if (!conn.modes_ptr)
+                       goto err_allocs;
+       }
 
-       if (conn.count_encoders)
+       if (conn.count_encoders) {
                conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));
+               if (!conn.encoders_ptr)
+                       goto err_allocs;
+       }
 
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
                goto err_allocs;
 
+       /* The number of available connectors and etc may have changed with a
+        * hotplug event in between the ioctls, in which case the field is
+        * silently ignored by the kernel.
+        */
+       if (counts.count_props < conn.count_props ||
+           counts.count_modes < conn.count_modes ||
+           counts.count_encoders < conn.count_encoders) {
+               drmFree(U642VOID(conn.props_ptr));
+               drmFree(U642VOID(conn.prop_values_ptr));
+               drmFree(U642VOID(conn.modes_ptr));
+               drmFree(U642VOID(conn.encoders_ptr));
+
+               goto retry;
+       }
+
        if(!(r = drmMalloc(sizeof(*r)))) {
                goto err_allocs;
        }
@@ -449,7 +479,6 @@ drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
        /* convert subpixel from kernel to userspace */
        r->subpixel     = conn.subpixel + 1;
        r->count_modes  = conn.count_modes;
-       /* TODO we should test if these alloc & cpy fails. */
        r->count_props  = conn.count_props;
        r->props        = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));
        r->prop_values  = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));
@@ -459,8 +488,17 @@ drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
        r->connector_type  = conn.connector_type;
        r->connector_type_id = conn.connector_type_id;
 
-       if (!r->props || !r->prop_values || !r->modes || !r->encoders)
-               goto err_allocs;
+       if ((r->count_props && !r->props) ||
+           (r->count_props && !r->prop_values) ||
+           (r->count_modes && !r->modes) ||
+           (r->count_encoders && !r->encoders)) {
+               drmFree(r->props);
+               drmFree(r->prop_values);
+               drmFree(r->modes);
+               drmFree(r->encoders);
+               drmFree(r);
+               r = 0;
+       }
 
 err_allocs:
        drmFree(U642VOID(conn.prop_values_ptr));
@@ -478,7 +516,7 @@ int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_inf
        memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
        res.connector_id = connector_id;
 
-       return drmIoctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
+       return DRM_IOCTL(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
 }
 
 int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
@@ -488,7 +526,7 @@ int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_inf
        memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
        res.connector_id = connector_id;
 
-       return drmIoctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
+       return DRM_IOCTL(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
 }
 
 
@@ -581,7 +619,7 @@ drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id)
        }
 
        if (!(r = drmMalloc(sizeof(*r))))
-               return NULL;
+               goto err_allocs;
 
        r->id = blob.blob_id;
        r->length = blob.length;
@@ -605,16 +643,12 @@ int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property
                             uint64_t value)
 {
        struct drm_mode_connector_set_property osp;
-       int ret;
 
        osp.connector_id = connector_id;
        osp.prop_id = property_id;
        osp.value = value;
 
-       if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)))
-               return ret;
-
-       return 0;
+       return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp);
 }
 
 /*
@@ -683,7 +717,6 @@ int drmCheckModesettingSupported(const char *busid)
 int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
                        uint16_t *red, uint16_t *green, uint16_t *blue)
 {
-       int ret;
        struct drm_mode_crtc_lut l;
 
        l.crtc_id = crtc_id;
@@ -692,16 +725,12 @@ int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
        l.green = VOID2U64(green);
        l.blue = VOID2U64(blue);
 
-       if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_GETGAMMA, &l)))
-               return ret;
-
-       return 0;
+       return DRM_IOCTL(fd, DRM_IOCTL_MODE_GETGAMMA, &l);
 }
 
 int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
                        uint16_t *red, uint16_t *green, uint16_t *blue)
 {
-       int ret;
        struct drm_mode_crtc_lut l;
 
        l.crtc_id = crtc_id;
@@ -710,10 +739,7 @@ int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
        l.green = VOID2U64(green);
        l.blue = VOID2U64(blue);
 
-       if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETGAMMA, &l)))
-               return ret;
-
-       return 0;
+       return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l);
 }
 
 int drmHandleEvent(int fd, drmEventContextPtr evctx)
@@ -778,5 +804,5 @@ int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id,
        flip.flags = flags;
        flip.reserved = 0;
 
-       return drmIoctl(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip);
+       return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip);
 }