Back to index

libdrm  2.4.37
xf86drmMode.c
Go to the documentation of this file.
00001 /*
00002  * \file xf86drmMode.c
00003  * Header for DRM modesetting interface.
00004  *
00005  * \author Jakob Bornecrantz <wallbraker@gmail.com>
00006  *
00007  * \par Acknowledgements:
00008  * Feb 2007, Dave Airlie <airlied@linux.ie>
00009  */
00010 
00011 /*
00012  * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00013  * Copyright (c) 2007-2008 Dave Airlie <airlied@linux.ie>
00014  * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com>
00015  *
00016  * Permission is hereby granted, free of charge, to any person obtaining a
00017  * copy of this software and associated documentation files (the "Software"),
00018  * to deal in the Software without restriction, including without limitation
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00020  * and/or sell copies of the Software, and to permit persons to whom the
00021  * Software is furnished to do so, subject to the following conditions:
00022  *
00023  * The above copyright notice and this permission notice shall be included in
00024  * all copies or substantial portions of the Software.
00025  *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00029  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00030  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00031  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
00032  * IN THE SOFTWARE.
00033  *
00034  */
00035 
00036 /*
00037  * TODO the types we are after are defined in diffrent headers on diffrent
00038  * platforms find which headers to include to get uint32_t
00039  */
00040 #include <stdint.h>
00041 #include <sys/ioctl.h>
00042 #include <stdio.h>
00043 
00044 #include "xf86drmMode.h"
00045 #include "xf86drm.h"
00046 #include <drm.h>
00047 #include <string.h>
00048 #include <dirent.h>
00049 #include <unistd.h>
00050 #include <errno.h>
00051 
00052 #define U642VOID(x) ((void *)(unsigned long)(x))
00053 #define VOID2U64(x) ((uint64_t)(unsigned long)(x))
00054 
00055 static inline int DRM_IOCTL(int fd, unsigned long cmd, void *arg)
00056 {
00057        int ret = drmIoctl(fd, cmd, arg);
00058        return ret < 0 ? -errno : ret;
00059 }
00060 
00061 /*
00062  * Util functions
00063  */
00064 
00065 void* drmAllocCpy(void *array, int count, int entry_size)
00066 {
00067        char *r;
00068        int i;
00069 
00070        if (!count || !array || !entry_size)
00071               return 0;
00072 
00073        if (!(r = drmMalloc(count*entry_size)))
00074               return 0;
00075 
00076        for (i = 0; i < count; i++)
00077               memcpy(r+(entry_size*i), array+(entry_size*i), entry_size);
00078 
00079        return r;
00080 }
00081 
00082 /*
00083  * A couple of free functions.
00084  */
00085 
00086 void drmModeFreeModeInfo(drmModeModeInfoPtr ptr)
00087 {
00088        if (!ptr)
00089               return;
00090 
00091        drmFree(ptr);
00092 }
00093 
00094 void drmModeFreeResources(drmModeResPtr ptr)
00095 {
00096        if (!ptr)
00097               return;
00098 
00099        drmFree(ptr->fbs);
00100        drmFree(ptr->crtcs);
00101        drmFree(ptr->connectors);
00102        drmFree(ptr->encoders);
00103        drmFree(ptr);
00104 
00105 }
00106 
00107 void drmModeFreeFB(drmModeFBPtr ptr)
00108 {
00109        if (!ptr)
00110               return;
00111 
00112        /* we might add more frees later. */
00113        drmFree(ptr);
00114 }
00115 
00116 void drmModeFreeCrtc(drmModeCrtcPtr ptr)
00117 {
00118        if (!ptr)
00119               return;
00120 
00121        drmFree(ptr);
00122 
00123 }
00124 
00125 void drmModeFreeConnector(drmModeConnectorPtr ptr)
00126 {
00127        if (!ptr)
00128               return;
00129 
00130        drmFree(ptr->encoders);
00131        drmFree(ptr->prop_values);
00132        drmFree(ptr->props);
00133        drmFree(ptr->modes);
00134        drmFree(ptr);
00135 
00136 }
00137 
00138 void drmModeFreeEncoder(drmModeEncoderPtr ptr)
00139 {
00140        drmFree(ptr);
00141 }
00142 
00143 /*
00144  * ModeSetting functions.
00145  */
00146 
00147 drmModeResPtr drmModeGetResources(int fd)
00148 {
00149        struct drm_mode_card_res res, counts;
00150        drmModeResPtr r = 0;
00151 
00152 retry:
00153        memset(&res, 0, sizeof(struct drm_mode_card_res));
00154        if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
00155               return 0;
00156 
00157        counts = res;
00158 
00159        if (res.count_fbs) {
00160               res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t)));
00161               if (!res.fb_id_ptr)
00162                      goto err_allocs;
00163        }
00164        if (res.count_crtcs) {
00165               res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t)));
00166               if (!res.crtc_id_ptr)
00167                      goto err_allocs;
00168        }
00169        if (res.count_connectors) {
00170               res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t)));
00171               if (!res.connector_id_ptr)
00172                      goto err_allocs;
00173        }
00174        if (res.count_encoders) {
00175               res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t)));
00176               if (!res.encoder_id_ptr)
00177                      goto err_allocs;
00178        }
00179 
00180        if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
00181               goto err_allocs;
00182 
00183        /* The number of available connectors and etc may have changed with a
00184         * hotplug event in between the ioctls, in which case the field is
00185         * silently ignored by the kernel.
00186         */
00187        if (counts.count_fbs < res.count_fbs ||
00188            counts.count_crtcs < res.count_crtcs ||
00189            counts.count_connectors < res.count_connectors ||
00190            counts.count_encoders < res.count_encoders)
00191        {
00192               drmFree(U642VOID(res.fb_id_ptr));
00193               drmFree(U642VOID(res.crtc_id_ptr));
00194               drmFree(U642VOID(res.connector_id_ptr));
00195               drmFree(U642VOID(res.encoder_id_ptr));
00196 
00197               goto retry;
00198        }
00199 
00200        /*
00201         * return
00202         */
00203        if (!(r = drmMalloc(sizeof(*r))))
00204               goto err_allocs;
00205 
00206        r->min_width     = res.min_width;
00207        r->max_width     = res.max_width;
00208        r->min_height    = res.min_height;
00209        r->max_height    = res.max_height;
00210        r->count_fbs     = res.count_fbs;
00211        r->count_crtcs   = res.count_crtcs;
00212        r->count_connectors = res.count_connectors;
00213        r->count_encoders = res.count_encoders;
00214 
00215        r->fbs        = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t));
00216        r->crtcs      = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t));
00217        r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t));
00218        r->encoders   = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t));
00219        if ((res.count_fbs && !r->fbs) ||
00220            (res.count_crtcs && !r->crtcs) ||
00221            (res.count_connectors && !r->connectors) ||
00222            (res.count_encoders && !r->encoders))
00223        {
00224               drmFree(r->fbs);
00225               drmFree(r->crtcs);
00226               drmFree(r->connectors);
00227               drmFree(r->encoders);
00228               drmFree(r);
00229               r = 0;
00230        }
00231 
00232 err_allocs:
00233        drmFree(U642VOID(res.fb_id_ptr));
00234        drmFree(U642VOID(res.crtc_id_ptr));
00235        drmFree(U642VOID(res.connector_id_ptr));
00236        drmFree(U642VOID(res.encoder_id_ptr));
00237 
00238        return r;
00239 }
00240 
00241 int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
00242                  uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
00243                uint32_t *buf_id)
00244 {
00245        struct drm_mode_fb_cmd f;
00246        int ret;
00247 
00248        f.width  = width;
00249        f.height = height;
00250        f.pitch  = pitch;
00251        f.bpp    = bpp;
00252        f.depth  = depth;
00253        f.handle = bo_handle;
00254 
00255        if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f)))
00256               return ret;
00257 
00258        *buf_id = f.fb_id;
00259        return 0;
00260 }
00261 
00262 int drmModeAddFB2(int fd, uint32_t width, uint32_t height,
00263                 uint32_t pixel_format, uint32_t bo_handles[4],
00264                 uint32_t pitches[4], uint32_t offsets[4],
00265                 uint32_t *buf_id, uint32_t flags)
00266 {
00267        struct drm_mode_fb_cmd2 f;
00268        int ret;
00269 
00270        f.width  = width;
00271        f.height = height;
00272        f.pixel_format = pixel_format;
00273        f.flags = flags;
00274        memcpy(f.handles, bo_handles, 4 * sizeof(bo_handles[0]));
00275        memcpy(f.pitches, pitches, 4 * sizeof(pitches[0]));
00276        memcpy(f.offsets, offsets, 4 * sizeof(offsets[0]));
00277 
00278        if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB2, &f)))
00279               return ret;
00280 
00281        *buf_id = f.fb_id;
00282        return 0;
00283 }
00284 
00285 int drmModeRmFB(int fd, uint32_t bufferId)
00286 {
00287        return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
00288 
00289 
00290 }
00291 
00292 drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
00293 {
00294        struct drm_mode_fb_cmd info;
00295        drmModeFBPtr r;
00296 
00297        info.fb_id = buf;
00298 
00299        if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info))
00300               return NULL;
00301 
00302        if (!(r = drmMalloc(sizeof(*r))))
00303               return NULL;
00304 
00305        r->fb_id = info.fb_id;
00306        r->width = info.width;
00307        r->height = info.height;
00308        r->pitch = info.pitch;
00309        r->bpp = info.bpp;
00310        r->handle = info.handle;
00311        r->depth = info.depth;
00312 
00313        return r;
00314 }
00315 
00316 int drmModeDirtyFB(int fd, uint32_t bufferId,
00317                  drmModeClipPtr clips, uint32_t num_clips)
00318 {
00319        struct drm_mode_fb_dirty_cmd dirty = { 0 };
00320 
00321        dirty.fb_id = bufferId;
00322        dirty.clips_ptr = VOID2U64(clips);
00323        dirty.num_clips = num_clips;
00324 
00325        return DRM_IOCTL(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty);
00326 }
00327 
00328 
00329 /*
00330  * Crtc functions
00331  */
00332 
00333 drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
00334 {
00335        struct drm_mode_crtc crtc;
00336        drmModeCrtcPtr r;
00337 
00338        crtc.crtc_id = crtcId;
00339 
00340        if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
00341               return 0;
00342 
00343        /*
00344         * return
00345         */
00346 
00347        if (!(r = drmMalloc(sizeof(*r))))
00348               return 0;
00349 
00350        r->crtc_id         = crtc.crtc_id;
00351        r->x               = crtc.x;
00352        r->y               = crtc.y;
00353        r->mode_valid      = crtc.mode_valid;
00354        if (r->mode_valid)
00355               memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));
00356        r->buffer_id       = crtc.fb_id;
00357        r->gamma_size      = crtc.gamma_size;
00358        return r;
00359 }
00360 
00361 
00362 int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
00363                    uint32_t x, uint32_t y, uint32_t *connectors, int count,
00364                  drmModeModeInfoPtr mode)
00365 {
00366        struct drm_mode_crtc crtc;
00367 
00368        crtc.x             = x;
00369        crtc.y             = y;
00370        crtc.crtc_id       = crtcId;
00371        crtc.fb_id         = bufferId;
00372        crtc.set_connectors_ptr = VOID2U64(connectors);
00373        crtc.count_connectors = count;
00374        if (mode) {
00375          memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
00376          crtc.mode_valid = 1;
00377        } else
00378          crtc.mode_valid = 0;
00379 
00380        return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
00381 }
00382 
00383 /*
00384  * Cursor manipulation
00385  */
00386 
00387 int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height)
00388 {
00389        struct drm_mode_cursor arg;
00390 
00391        arg.flags = DRM_MODE_CURSOR_BO;
00392        arg.crtc_id = crtcId;
00393        arg.width = width;
00394        arg.height = height;
00395        arg.handle = bo_handle;
00396 
00397        return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg);
00398 }
00399 
00400 int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
00401 {
00402        struct drm_mode_cursor arg;
00403 
00404        arg.flags = DRM_MODE_CURSOR_MOVE;
00405        arg.crtc_id = crtcId;
00406        arg.x = x;
00407        arg.y = y;
00408 
00409        return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg);
00410 }
00411 
00412 /*
00413  * Encoder get
00414  */
00415 drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
00416 {
00417        struct drm_mode_get_encoder enc;
00418        drmModeEncoderPtr r = NULL;
00419 
00420        enc.encoder_id = encoder_id;
00421        enc.encoder_type = 0;
00422        enc.possible_crtcs = 0;
00423        enc.possible_clones = 0;
00424 
00425        if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc))
00426               return 0;
00427 
00428        if (!(r = drmMalloc(sizeof(*r))))
00429               return 0;
00430 
00431        r->encoder_id = enc.encoder_id;
00432        r->crtc_id = enc.crtc_id;
00433        r->encoder_type = enc.encoder_type;
00434        r->possible_crtcs = enc.possible_crtcs;
00435        r->possible_clones = enc.possible_clones;
00436 
00437        return r;
00438 }
00439 
00440 /*
00441  * Connector manipulation
00442  */
00443 
00444 drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
00445 {
00446        struct drm_mode_get_connector conn, counts;
00447        drmModeConnectorPtr r = NULL;
00448 
00449 retry:
00450        memset(&conn, 0, sizeof(struct drm_mode_get_connector));
00451        conn.connector_id = connector_id;
00452 
00453        if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
00454               return 0;
00455 
00456        counts = conn;
00457 
00458        if (conn.count_props) {
00459               conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
00460               if (!conn.props_ptr)
00461                      goto err_allocs;
00462               conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
00463               if (!conn.prop_values_ptr)
00464                      goto err_allocs;
00465        }
00466 
00467        if (conn.count_modes) {
00468               conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));
00469               if (!conn.modes_ptr)
00470                      goto err_allocs;
00471        }
00472 
00473        if (conn.count_encoders) {
00474               conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));
00475               if (!conn.encoders_ptr)
00476                      goto err_allocs;
00477        }
00478 
00479        if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
00480               goto err_allocs;
00481 
00482        /* The number of available connectors and etc may have changed with a
00483         * hotplug event in between the ioctls, in which case the field is
00484         * silently ignored by the kernel.
00485         */
00486        if (counts.count_props < conn.count_props ||
00487            counts.count_modes < conn.count_modes ||
00488            counts.count_encoders < conn.count_encoders) {
00489               drmFree(U642VOID(conn.props_ptr));
00490               drmFree(U642VOID(conn.prop_values_ptr));
00491               drmFree(U642VOID(conn.modes_ptr));
00492               drmFree(U642VOID(conn.encoders_ptr));
00493 
00494               goto retry;
00495        }
00496 
00497        if(!(r = drmMalloc(sizeof(*r)))) {
00498               goto err_allocs;
00499        }
00500 
00501        r->connector_id = conn.connector_id;
00502        r->encoder_id = conn.encoder_id;
00503        r->connection   = conn.connection;
00504        r->mmWidth      = conn.mm_width;
00505        r->mmHeight     = conn.mm_height;
00506        /* convert subpixel from kernel to userspace */
00507        r->subpixel     = conn.subpixel + 1;
00508        r->count_modes  = conn.count_modes;
00509        r->count_props  = conn.count_props;
00510        r->props        = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));
00511        r->prop_values  = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));
00512        r->modes        = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo));
00513        r->count_encoders = conn.count_encoders;
00514        r->encoders     = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t));
00515        r->connector_type  = conn.connector_type;
00516        r->connector_type_id = conn.connector_type_id;
00517 
00518        if ((r->count_props && !r->props) ||
00519            (r->count_props && !r->prop_values) ||
00520            (r->count_modes && !r->modes) ||
00521            (r->count_encoders && !r->encoders)) {
00522               drmFree(r->props);
00523               drmFree(r->prop_values);
00524               drmFree(r->modes);
00525               drmFree(r->encoders);
00526               drmFree(r);
00527               r = 0;
00528        }
00529 
00530 err_allocs:
00531        drmFree(U642VOID(conn.prop_values_ptr));
00532        drmFree(U642VOID(conn.props_ptr));
00533        drmFree(U642VOID(conn.modes_ptr));
00534        drmFree(U642VOID(conn.encoders_ptr));
00535 
00536        return r;
00537 }
00538 
00539 int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
00540 {
00541        struct drm_mode_mode_cmd res;
00542 
00543        memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
00544        res.connector_id = connector_id;
00545 
00546        return DRM_IOCTL(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
00547 }
00548 
00549 int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
00550 {
00551        struct drm_mode_mode_cmd res;
00552 
00553        memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
00554        res.connector_id = connector_id;
00555 
00556        return DRM_IOCTL(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
00557 }
00558 
00559 
00560 drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
00561 {
00562        struct drm_mode_get_property prop;
00563        drmModePropertyPtr r;
00564 
00565        prop.prop_id = property_id;
00566        prop.count_enum_blobs = 0;
00567        prop.count_values = 0;
00568        prop.flags = 0;
00569        prop.enum_blob_ptr = 0;
00570        prop.values_ptr = 0;
00571 
00572        if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
00573               return 0;
00574 
00575        if (prop.count_values)
00576               prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t)));
00577 
00578        if (prop.count_enum_blobs && (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
00579               prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)));
00580 
00581        if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) {
00582               prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
00583               prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
00584        }
00585 
00586        if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) {
00587               r = NULL;
00588               goto err_allocs;
00589        }
00590 
00591        if (!(r = drmMalloc(sizeof(*r))))
00592               return NULL;
00593 
00594        r->prop_id = prop.prop_id;
00595        r->count_values = prop.count_values;
00596 
00597        r->flags = prop.flags;
00598        if (prop.count_values)
00599               r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t));
00600        if (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
00601               r->count_enums = prop.count_enum_blobs;
00602               r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum));
00603        } else if (prop.flags & DRM_MODE_PROP_BLOB) {
00604               r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t));
00605               r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t));
00606               r->count_blobs = prop.count_enum_blobs;
00607        }
00608        strncpy(r->name, prop.name, DRM_PROP_NAME_LEN);
00609        r->name[DRM_PROP_NAME_LEN-1] = 0;
00610 
00611 err_allocs:
00612        drmFree(U642VOID(prop.values_ptr));
00613        drmFree(U642VOID(prop.enum_blob_ptr));
00614 
00615        return r;
00616 }
00617 
00618 void drmModeFreeProperty(drmModePropertyPtr ptr)
00619 {
00620        if (!ptr)
00621               return;
00622 
00623        drmFree(ptr->values);
00624        drmFree(ptr->enums);
00625        drmFree(ptr);
00626 }
00627 
00628 drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id)
00629 {
00630        struct drm_mode_get_blob blob;
00631        drmModePropertyBlobPtr r;
00632 
00633        blob.length = 0;
00634        blob.data = 0;
00635        blob.blob_id = blob_id;
00636 
00637        if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
00638               return NULL;
00639 
00640        if (blob.length)
00641               blob.data = VOID2U64(drmMalloc(blob.length));
00642 
00643        if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
00644               r = NULL;
00645               goto err_allocs;
00646        }
00647 
00648        if (!(r = drmMalloc(sizeof(*r))))
00649               goto err_allocs;
00650 
00651        r->id = blob.blob_id;
00652        r->length = blob.length;
00653        r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length);
00654 
00655 err_allocs:
00656        drmFree(U642VOID(blob.data));
00657        return r;
00658 }
00659 
00660 void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
00661 {
00662        if (!ptr)
00663               return;
00664 
00665        drmFree(ptr->data);
00666        drmFree(ptr);
00667 }
00668 
00669 int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
00670                           uint64_t value)
00671 {
00672        struct drm_mode_connector_set_property osp;
00673 
00674        osp.connector_id = connector_id;
00675        osp.prop_id = property_id;
00676        osp.value = value;
00677 
00678        return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp);
00679 }
00680 
00681 /*
00682  * checks if a modesetting capable driver has attached to the pci id
00683  * returns 0 if modesetting supported.
00684  *  -EINVAL or invalid bus id
00685  *  -ENOSYS if no modesetting support
00686 */
00687 int drmCheckModesettingSupported(const char *busid)
00688 {
00689 #ifdef __linux__
00690        char pci_dev_dir[1024];
00691        int domain, bus, dev, func;
00692        DIR *sysdir;
00693        struct dirent *dent;
00694        int found = 0, ret;
00695 
00696        ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func);
00697        if (ret != 4)
00698               return -EINVAL;
00699 
00700        sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm",
00701               domain, bus, dev, func);
00702 
00703        sysdir = opendir(pci_dev_dir);
00704        if (sysdir) {
00705               dent = readdir(sysdir);
00706               while (dent) {
00707                      if (!strncmp(dent->d_name, "controlD", 8)) {
00708                             found = 1;
00709                             break;
00710                      }
00711 
00712                      dent = readdir(sysdir);
00713               }
00714               closedir(sysdir);
00715               if (found)
00716                      return 0;
00717        }
00718 
00719        sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
00720               domain, bus, dev, func);
00721 
00722        sysdir = opendir(pci_dev_dir);
00723        if (!sysdir)
00724               return -EINVAL;
00725 
00726        dent = readdir(sysdir);
00727        while (dent) {
00728               if (!strncmp(dent->d_name, "drm:controlD", 12)) {
00729                      found = 1;
00730                      break;
00731               }
00732 
00733               dent = readdir(sysdir);
00734        }
00735 
00736        closedir(sysdir);
00737        if (found)
00738               return 0;
00739 #endif
00740        return -ENOSYS;
00741 
00742 }
00743 
00744 int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
00745                      uint16_t *red, uint16_t *green, uint16_t *blue)
00746 {
00747        struct drm_mode_crtc_lut l;
00748 
00749        l.crtc_id = crtc_id;
00750        l.gamma_size = size;
00751        l.red = VOID2U64(red);
00752        l.green = VOID2U64(green);
00753        l.blue = VOID2U64(blue);
00754 
00755        return DRM_IOCTL(fd, DRM_IOCTL_MODE_GETGAMMA, &l);
00756 }
00757 
00758 int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
00759                      uint16_t *red, uint16_t *green, uint16_t *blue)
00760 {
00761        struct drm_mode_crtc_lut l;
00762 
00763        l.crtc_id = crtc_id;
00764        l.gamma_size = size;
00765        l.red = VOID2U64(red);
00766        l.green = VOID2U64(green);
00767        l.blue = VOID2U64(blue);
00768 
00769        return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l);
00770 }
00771 
00772 int drmHandleEvent(int fd, drmEventContextPtr evctx)
00773 {
00774        char buffer[1024];
00775        int len, i;
00776        struct drm_event *e;
00777        struct drm_event_vblank *vblank;
00778        
00779        /* The DRM read semantics guarantees that we always get only
00780         * complete events. */
00781 
00782        len = read(fd, buffer, sizeof buffer);
00783        if (len == 0)
00784               return 0;
00785        if (len < sizeof *e)
00786               return -1;
00787 
00788        i = 0;
00789        while (i < len) {
00790               e = (struct drm_event *) &buffer[i];
00791               switch (e->type) {
00792               case DRM_EVENT_VBLANK:
00793                      if (evctx->version < 1 ||
00794                          evctx->vblank_handler == NULL)
00795                             break;
00796                      vblank = (struct drm_event_vblank *) e;
00797                      evctx->vblank_handler(fd,
00798                                          vblank->sequence, 
00799                                          vblank->tv_sec,
00800                                          vblank->tv_usec,
00801                                          U642VOID (vblank->user_data));
00802                      break;
00803               case DRM_EVENT_FLIP_COMPLETE:
00804                      if (evctx->version < 2 ||
00805                          evctx->page_flip_handler == NULL)
00806                             break;
00807                      vblank = (struct drm_event_vblank *) e;
00808                      evctx->page_flip_handler(fd,
00809                                            vblank->sequence,
00810                                            vblank->tv_sec,
00811                                            vblank->tv_usec,
00812                                            U642VOID (vblank->user_data));
00813                      break;
00814               default:
00815                      break;
00816               }
00817               i += e->length;
00818        }
00819 
00820        return 0;
00821 }
00822 
00823 int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id,
00824                   uint32_t flags, void *user_data)
00825 {
00826        struct drm_mode_crtc_page_flip flip;
00827 
00828        flip.fb_id = fb_id;
00829        flip.crtc_id = crtc_id;
00830        flip.user_data = VOID2U64(user_data);
00831        flip.flags = flags;
00832        flip.reserved = 0;
00833 
00834        return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip);
00835 }
00836 
00837 int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id,
00838                   uint32_t fb_id, uint32_t flags,
00839                   uint32_t crtc_x, uint32_t crtc_y,
00840                   uint32_t crtc_w, uint32_t crtc_h,
00841                   uint32_t src_x, uint32_t src_y,
00842                   uint32_t src_w, uint32_t src_h)
00843 
00844 {
00845        struct drm_mode_set_plane s;
00846 
00847        s.plane_id = plane_id;
00848        s.crtc_id = crtc_id;
00849        s.fb_id = fb_id;
00850        s.flags = flags;
00851        s.crtc_x = crtc_x;
00852        s.crtc_y = crtc_y;
00853        s.crtc_w = crtc_w;
00854        s.crtc_h = crtc_h;
00855        s.src_x = src_x;
00856        s.src_y = src_y;
00857        s.src_w = src_w;
00858        s.src_h = src_h;
00859 
00860        return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPLANE, &s);
00861 }
00862 
00863 
00864 drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id)
00865 {
00866        struct drm_mode_get_plane ovr, counts;
00867        drmModePlanePtr r = 0;
00868 
00869 retry:
00870        memset(&ovr, 0, sizeof(struct drm_mode_get_plane));
00871        ovr.plane_id = plane_id;
00872        if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr))
00873               return 0;
00874 
00875        counts = ovr;
00876 
00877        if (ovr.count_format_types) {
00878               ovr.format_type_ptr = VOID2U64(drmMalloc(ovr.count_format_types *
00879                                                   sizeof(uint32_t)));
00880               if (!ovr.format_type_ptr)
00881                      goto err_allocs;
00882        }
00883 
00884        if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr))
00885               goto err_allocs;
00886 
00887        if (counts.count_format_types < ovr.count_format_types) {
00888               drmFree(U642VOID(ovr.format_type_ptr));
00889               goto retry;
00890        }
00891 
00892        if (!(r = drmMalloc(sizeof(*r))))
00893               goto err_allocs;
00894 
00895        r->count_formats = ovr.count_format_types;
00896        r->plane_id = ovr.plane_id;
00897        r->crtc_id = ovr.crtc_id;
00898        r->fb_id = ovr.fb_id;
00899        r->possible_crtcs = ovr.possible_crtcs;
00900        r->gamma_size = ovr.gamma_size;
00901        r->formats = drmAllocCpy(U642VOID(ovr.format_type_ptr),
00902                              ovr.count_format_types, sizeof(uint32_t));
00903        if (ovr.count_format_types && !r->formats) {
00904               drmFree(r->formats);
00905               drmFree(r);
00906               r = 0;
00907        }
00908 
00909 err_allocs:
00910        drmFree(U642VOID(ovr.format_type_ptr));
00911 
00912        return r;
00913 }
00914 
00915 void drmModeFreePlane(drmModePlanePtr ptr)
00916 {
00917        if (!ptr)
00918               return;
00919 
00920        drmFree(ptr->formats);
00921        drmFree(ptr);
00922 }
00923 
00924 drmModePlaneResPtr drmModeGetPlaneResources(int fd)
00925 {
00926        struct drm_mode_get_plane_res res, counts;
00927        drmModePlaneResPtr r = 0;
00928 
00929 retry:
00930        memset(&res, 0, sizeof(struct drm_mode_get_plane_res));
00931        if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res))
00932               return 0;
00933 
00934        counts = res;
00935 
00936        if (res.count_planes) {
00937               res.plane_id_ptr = VOID2U64(drmMalloc(res.count_planes *
00938                                                  sizeof(uint32_t)));
00939               if (!res.plane_id_ptr)
00940                      goto err_allocs;
00941        }
00942 
00943        if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res))
00944               goto err_allocs;
00945 
00946        if (counts.count_planes < res.count_planes) {
00947               drmFree(U642VOID(res.plane_id_ptr));
00948               goto retry;
00949        }
00950 
00951        if (!(r = drmMalloc(sizeof(*r))))
00952               goto err_allocs;
00953 
00954        r->count_planes = res.count_planes;
00955        r->planes = drmAllocCpy(U642VOID(res.plane_id_ptr),
00956                               res.count_planes, sizeof(uint32_t));
00957        if (res.count_planes && !r->planes) {
00958               drmFree(r->planes);
00959               drmFree(r);
00960               r = 0;
00961        }
00962 
00963 err_allocs:
00964        drmFree(U642VOID(res.plane_id_ptr));
00965 
00966        return r;
00967 }
00968 
00969 void drmModeFreePlaneResources(drmModePlaneResPtr ptr)
00970 {
00971        if (!ptr)
00972               return;
00973 
00974        drmFree(ptr->planes);
00975        drmFree(ptr);
00976 }
00977 
00978 drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd,
00979                                                 uint32_t object_id,
00980                                                 uint32_t object_type)
00981 {
00982        struct drm_mode_obj_get_properties properties;
00983        drmModeObjectPropertiesPtr ret = NULL;
00984        uint32_t count;
00985 
00986 retry:
00987        memset(&properties, 0, sizeof(struct drm_mode_obj_get_properties));
00988        properties.obj_id = object_id;
00989        properties.obj_type = object_type;
00990 
00991        if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties))
00992               return 0;
00993 
00994        count = properties.count_props;
00995 
00996        if (count) {
00997               properties.props_ptr = VOID2U64(drmMalloc(count *
00998                                                    sizeof(uint32_t)));
00999               if (!properties.props_ptr)
01000                      goto err_allocs;
01001               properties.prop_values_ptr = VOID2U64(drmMalloc(count *
01002                                                 sizeof(uint64_t)));
01003               if (!properties.prop_values_ptr)
01004                      goto err_allocs;
01005        }
01006 
01007        if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties))
01008               goto err_allocs;
01009 
01010        if (count < properties.count_props) {
01011               drmFree(U642VOID(properties.props_ptr));
01012               drmFree(U642VOID(properties.prop_values_ptr));
01013               goto retry;
01014        }
01015        count = properties.count_props;
01016 
01017        ret = drmMalloc(sizeof(*ret));
01018        if (!ret)
01019               goto err_allocs;
01020 
01021        ret->count_props = count;
01022        ret->props = drmAllocCpy(U642VOID(properties.props_ptr),
01023                              count, sizeof(uint32_t));
01024        ret->prop_values = drmAllocCpy(U642VOID(properties.prop_values_ptr),
01025                                    count, sizeof(uint64_t));
01026        if (ret->count_props && (!ret->props || !ret->prop_values)) {
01027               drmFree(ret->props);
01028               drmFree(ret->prop_values);
01029               drmFree(ret);
01030               ret = NULL;
01031        }
01032 
01033 err_allocs:
01034        drmFree(U642VOID(properties.props_ptr));
01035        drmFree(U642VOID(properties.prop_values_ptr));
01036        return ret;
01037 }
01038 
01039 void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr)
01040 {
01041        if (!ptr)
01042               return;
01043        drmFree(ptr->props);
01044        drmFree(ptr->prop_values);
01045        drmFree(ptr);
01046 }
01047 
01048 int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type,
01049                           uint32_t property_id, uint64_t value)
01050 {
01051        struct drm_mode_obj_set_property prop;
01052 
01053        prop.value = value;
01054        prop.prop_id = property_id;
01055        prop.obj_id = object_id;
01056        prop.obj_type = object_type;
01057 
01058        return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop);
01059 }