xf86drmMode.c revision 7811b380
1/* 2 * \file xf86drmMode.c 3 * Header for DRM modesetting interface. 4 * 5 * \author Jakob Bornecrantz <wallbraker@gmail.com> 6 * 7 * \par Acknowledgements: 8 * Feb 2007, Dave Airlie <airlied@linux.ie> 9 */ 10 11/* 12 * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. 13 * Copyright (c) 2007-2008 Dave Airlie <airlied@linux.ie> 14 * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com> 15 * 16 * Permission is hereby granted, free of charge, to any person obtaining a 17 * copy of this software and associated documentation files (the "Software"), 18 * to deal in the Software without restriction, including without limitation 19 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 * and/or sell copies of the Software, and to permit persons to whom the 21 * Software is furnished to do so, subject to the following conditions: 22 * 23 * The above copyright notice and this permission notice shall be included in 24 * all copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 31 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 32 * IN THE SOFTWARE. 33 * 34 */ 35 36/* 37 * TODO the types we are after are defined in diffrent headers on diffrent 38 * platforms find which headers to include to get uint32_t 39 */ 40#include <stdint.h> 41#include <sys/ioctl.h> 42#include <stdio.h> 43 44#ifdef HAVE_CONFIG_H 45#include "config.h" 46#endif 47 48#include "xf86drmMode.h" 49#include "xf86drm.h" 50#include <drm.h> 51#include <string.h> 52#include <dirent.h> 53#include <unistd.h> 54#include <errno.h> 55 56#ifdef HAVE_VALGRIND 57#include <valgrind.h> 58#include <memcheck.h> 59#define VG(x) x 60#else 61#define VG(x) 62#endif 63 64#define VG_CLEAR(s) VG(memset(&s, 0, sizeof(s))) 65 66#define U642VOID(x) ((void *)(unsigned long)(x)) 67#define VOID2U64(x) ((uint64_t)(unsigned long)(x)) 68 69static inline int DRM_IOCTL(int fd, unsigned long cmd, void *arg) 70{ 71 int ret = drmIoctl(fd, cmd, arg); 72 return ret < 0 ? -errno : ret; 73} 74 75/* 76 * Util functions 77 */ 78 79void* drmAllocCpy(void *array, int count, int entry_size) 80{ 81 char *r; 82 int i; 83 84 if (!count || !array || !entry_size) 85 return 0; 86 87 if (!(r = drmMalloc(count*entry_size))) 88 return 0; 89 90 for (i = 0; i < count; i++) 91 memcpy(r+(entry_size*i), array+(entry_size*i), entry_size); 92 93 return r; 94} 95 96/* 97 * A couple of free functions. 98 */ 99 100void drmModeFreeModeInfo(drmModeModeInfoPtr ptr) 101{ 102 if (!ptr) 103 return; 104 105 drmFree(ptr); 106} 107 108void drmModeFreeResources(drmModeResPtr ptr) 109{ 110 if (!ptr) 111 return; 112 113 drmFree(ptr->fbs); 114 drmFree(ptr->crtcs); 115 drmFree(ptr->connectors); 116 drmFree(ptr->encoders); 117 drmFree(ptr); 118 119} 120 121void drmModeFreeFB(drmModeFBPtr ptr) 122{ 123 if (!ptr) 124 return; 125 126 /* we might add more frees later. */ 127 drmFree(ptr); 128} 129 130void drmModeFreeCrtc(drmModeCrtcPtr ptr) 131{ 132 if (!ptr) 133 return; 134 135 drmFree(ptr); 136 137} 138 139void drmModeFreeConnector(drmModeConnectorPtr ptr) 140{ 141 if (!ptr) 142 return; 143 144 drmFree(ptr->encoders); 145 drmFree(ptr->prop_values); 146 drmFree(ptr->props); 147 drmFree(ptr->modes); 148 drmFree(ptr); 149 150} 151 152void drmModeFreeEncoder(drmModeEncoderPtr ptr) 153{ 154 drmFree(ptr); 155} 156 157/* 158 * ModeSetting functions. 159 */ 160 161drmModeResPtr drmModeGetResources(int fd) 162{ 163 struct drm_mode_card_res res, counts; 164 drmModeResPtr r = 0; 165 166retry: 167 memset(&res, 0, sizeof(struct drm_mode_card_res)); 168 if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) 169 return 0; 170 171 counts = res; 172 173 if (res.count_fbs) { 174 res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t))); 175 if (!res.fb_id_ptr) 176 goto err_allocs; 177 } 178 if (res.count_crtcs) { 179 res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t))); 180 if (!res.crtc_id_ptr) 181 goto err_allocs; 182 } 183 if (res.count_connectors) { 184 res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t))); 185 if (!res.connector_id_ptr) 186 goto err_allocs; 187 } 188 if (res.count_encoders) { 189 res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t))); 190 if (!res.encoder_id_ptr) 191 goto err_allocs; 192 } 193 194 if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) 195 goto err_allocs; 196 197 /* The number of available connectors and etc may have changed with a 198 * hotplug event in between the ioctls, in which case the field is 199 * silently ignored by the kernel. 200 */ 201 if (counts.count_fbs < res.count_fbs || 202 counts.count_crtcs < res.count_crtcs || 203 counts.count_connectors < res.count_connectors || 204 counts.count_encoders < res.count_encoders) 205 { 206 drmFree(U642VOID(res.fb_id_ptr)); 207 drmFree(U642VOID(res.crtc_id_ptr)); 208 drmFree(U642VOID(res.connector_id_ptr)); 209 drmFree(U642VOID(res.encoder_id_ptr)); 210 211 goto retry; 212 } 213 214 /* 215 * return 216 */ 217 if (!(r = drmMalloc(sizeof(*r)))) 218 goto err_allocs; 219 220 r->min_width = res.min_width; 221 r->max_width = res.max_width; 222 r->min_height = res.min_height; 223 r->max_height = res.max_height; 224 r->count_fbs = res.count_fbs; 225 r->count_crtcs = res.count_crtcs; 226 r->count_connectors = res.count_connectors; 227 r->count_encoders = res.count_encoders; 228 229 r->fbs = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t)); 230 r->crtcs = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t)); 231 r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t)); 232 r->encoders = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t)); 233 if ((res.count_fbs && !r->fbs) || 234 (res.count_crtcs && !r->crtcs) || 235 (res.count_connectors && !r->connectors) || 236 (res.count_encoders && !r->encoders)) 237 { 238 drmFree(r->fbs); 239 drmFree(r->crtcs); 240 drmFree(r->connectors); 241 drmFree(r->encoders); 242 drmFree(r); 243 r = 0; 244 } 245 246err_allocs: 247 drmFree(U642VOID(res.fb_id_ptr)); 248 drmFree(U642VOID(res.crtc_id_ptr)); 249 drmFree(U642VOID(res.connector_id_ptr)); 250 drmFree(U642VOID(res.encoder_id_ptr)); 251 252 return r; 253} 254 255int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, 256 uint8_t bpp, uint32_t pitch, uint32_t bo_handle, 257 uint32_t *buf_id) 258{ 259 struct drm_mode_fb_cmd f; 260 int ret; 261 262 VG_CLEAR(f); 263 f.width = width; 264 f.height = height; 265 f.pitch = pitch; 266 f.bpp = bpp; 267 f.depth = depth; 268 f.handle = bo_handle; 269 270 if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f))) 271 return ret; 272 273 *buf_id = f.fb_id; 274 return 0; 275} 276 277int drmModeAddFB2(int fd, uint32_t width, uint32_t height, 278 uint32_t pixel_format, uint32_t bo_handles[4], 279 uint32_t pitches[4], uint32_t offsets[4], 280 uint32_t *buf_id, uint32_t flags) 281{ 282 struct drm_mode_fb_cmd2 f; 283 int ret; 284 285 f.width = width; 286 f.height = height; 287 f.pixel_format = pixel_format; 288 f.flags = flags; 289 memcpy(f.handles, bo_handles, 4 * sizeof(bo_handles[0])); 290 memcpy(f.pitches, pitches, 4 * sizeof(pitches[0])); 291 memcpy(f.offsets, offsets, 4 * sizeof(offsets[0])); 292 293 if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB2, &f))) 294 return ret; 295 296 *buf_id = f.fb_id; 297 return 0; 298} 299 300int drmModeRmFB(int fd, uint32_t bufferId) 301{ 302 return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId); 303 304 305} 306 307drmModeFBPtr drmModeGetFB(int fd, uint32_t buf) 308{ 309 struct drm_mode_fb_cmd info; 310 drmModeFBPtr r; 311 312 info.fb_id = buf; 313 314 if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info)) 315 return NULL; 316 317 if (!(r = drmMalloc(sizeof(*r)))) 318 return NULL; 319 320 r->fb_id = info.fb_id; 321 r->width = info.width; 322 r->height = info.height; 323 r->pitch = info.pitch; 324 r->bpp = info.bpp; 325 r->handle = info.handle; 326 r->depth = info.depth; 327 328 return r; 329} 330 331int drmModeDirtyFB(int fd, uint32_t bufferId, 332 drmModeClipPtr clips, uint32_t num_clips) 333{ 334 struct drm_mode_fb_dirty_cmd dirty = { 0 }; 335 336 dirty.fb_id = bufferId; 337 dirty.clips_ptr = VOID2U64(clips); 338 dirty.num_clips = num_clips; 339 340 return DRM_IOCTL(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty); 341} 342 343 344/* 345 * Crtc functions 346 */ 347 348drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) 349{ 350 struct drm_mode_crtc crtc; 351 drmModeCrtcPtr r; 352 353 VG_CLEAR(crtc); 354 crtc.crtc_id = crtcId; 355 356 if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc)) 357 return 0; 358 359 /* 360 * return 361 */ 362 363 if (!(r = drmMalloc(sizeof(*r)))) 364 return 0; 365 366 r->crtc_id = crtc.crtc_id; 367 r->x = crtc.x; 368 r->y = crtc.y; 369 r->mode_valid = crtc.mode_valid; 370 if (r->mode_valid) { 371 memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo)); 372 r->width = crtc.mode.hdisplay; 373 r->height = crtc.mode.vdisplay; 374 } 375 r->buffer_id = crtc.fb_id; 376 r->gamma_size = crtc.gamma_size; 377 return r; 378} 379 380 381int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, 382 uint32_t x, uint32_t y, uint32_t *connectors, int count, 383 drmModeModeInfoPtr mode) 384{ 385 struct drm_mode_crtc crtc; 386 387 VG_CLEAR(crtc); 388 crtc.x = x; 389 crtc.y = y; 390 crtc.crtc_id = crtcId; 391 crtc.fb_id = bufferId; 392 crtc.set_connectors_ptr = VOID2U64(connectors); 393 crtc.count_connectors = count; 394 if (mode) { 395 memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo)); 396 crtc.mode_valid = 1; 397 } else 398 crtc.mode_valid = 0; 399 400 return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc); 401} 402 403/* 404 * Cursor manipulation 405 */ 406 407int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height) 408{ 409 struct drm_mode_cursor arg; 410 411 arg.flags = DRM_MODE_CURSOR_BO; 412 arg.crtc_id = crtcId; 413 arg.width = width; 414 arg.height = height; 415 arg.handle = bo_handle; 416 417 return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); 418} 419 420int drmModeSetCursor2(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height, int32_t hot_x, int32_t hot_y) 421{ 422 struct drm_mode_cursor2 arg; 423 424 arg.flags = DRM_MODE_CURSOR_BO; 425 arg.crtc_id = crtcId; 426 arg.width = width; 427 arg.height = height; 428 arg.handle = bo_handle; 429 arg.hot_x = hot_x; 430 arg.hot_y = hot_y; 431 432 return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR2, &arg); 433} 434 435int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) 436{ 437 struct drm_mode_cursor arg; 438 439 arg.flags = DRM_MODE_CURSOR_MOVE; 440 arg.crtc_id = crtcId; 441 arg.x = x; 442 arg.y = y; 443 444 return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); 445} 446 447/* 448 * Encoder get 449 */ 450drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id) 451{ 452 struct drm_mode_get_encoder enc; 453 drmModeEncoderPtr r = NULL; 454 455 enc.encoder_id = encoder_id; 456 enc.crtc_id = 0; 457 enc.encoder_type = 0; 458 enc.possible_crtcs = 0; 459 enc.possible_clones = 0; 460 461 if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc)) 462 return 0; 463 464 if (!(r = drmMalloc(sizeof(*r)))) 465 return 0; 466 467 r->encoder_id = enc.encoder_id; 468 r->crtc_id = enc.crtc_id; 469 r->encoder_type = enc.encoder_type; 470 r->possible_crtcs = enc.possible_crtcs; 471 r->possible_clones = enc.possible_clones; 472 473 return r; 474} 475 476/* 477 * Connector manipulation 478 */ 479 480drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) 481{ 482 struct drm_mode_get_connector conn, counts; 483 drmModeConnectorPtr r = NULL; 484 485retry: 486 memset(&conn, 0, sizeof(struct drm_mode_get_connector)); 487 conn.connector_id = connector_id; 488 489 if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) 490 return 0; 491 492 counts = conn; 493 494 if (conn.count_props) { 495 conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t))); 496 if (!conn.props_ptr) 497 goto err_allocs; 498 conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t))); 499 if (!conn.prop_values_ptr) 500 goto err_allocs; 501 } 502 503 if (conn.count_modes) { 504 conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo))); 505 if (!conn.modes_ptr) 506 goto err_allocs; 507 } 508 509 if (conn.count_encoders) { 510 conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t))); 511 if (!conn.encoders_ptr) 512 goto err_allocs; 513 } 514 515 if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) 516 goto err_allocs; 517 518 /* The number of available connectors and etc may have changed with a 519 * hotplug event in between the ioctls, in which case the field is 520 * silently ignored by the kernel. 521 */ 522 if (counts.count_props < conn.count_props || 523 counts.count_modes < conn.count_modes || 524 counts.count_encoders < conn.count_encoders) { 525 drmFree(U642VOID(conn.props_ptr)); 526 drmFree(U642VOID(conn.prop_values_ptr)); 527 drmFree(U642VOID(conn.modes_ptr)); 528 drmFree(U642VOID(conn.encoders_ptr)); 529 530 goto retry; 531 } 532 533 if(!(r = drmMalloc(sizeof(*r)))) { 534 goto err_allocs; 535 } 536 537 r->connector_id = conn.connector_id; 538 r->encoder_id = conn.encoder_id; 539 r->connection = conn.connection; 540 r->mmWidth = conn.mm_width; 541 r->mmHeight = conn.mm_height; 542 /* convert subpixel from kernel to userspace */ 543 r->subpixel = conn.subpixel + 1; 544 r->count_modes = conn.count_modes; 545 r->count_props = conn.count_props; 546 r->props = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t)); 547 r->prop_values = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t)); 548 r->modes = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo)); 549 r->count_encoders = conn.count_encoders; 550 r->encoders = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t)); 551 r->connector_type = conn.connector_type; 552 r->connector_type_id = conn.connector_type_id; 553 554 if ((r->count_props && !r->props) || 555 (r->count_props && !r->prop_values) || 556 (r->count_modes && !r->modes) || 557 (r->count_encoders && !r->encoders)) { 558 drmFree(r->props); 559 drmFree(r->prop_values); 560 drmFree(r->modes); 561 drmFree(r->encoders); 562 drmFree(r); 563 r = 0; 564 } 565 566err_allocs: 567 drmFree(U642VOID(conn.prop_values_ptr)); 568 drmFree(U642VOID(conn.props_ptr)); 569 drmFree(U642VOID(conn.modes_ptr)); 570 drmFree(U642VOID(conn.encoders_ptr)); 571 572 return r; 573} 574 575int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) 576{ 577 struct drm_mode_mode_cmd res; 578 579 memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); 580 res.connector_id = connector_id; 581 582 return DRM_IOCTL(fd, DRM_IOCTL_MODE_ATTACHMODE, &res); 583} 584 585int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) 586{ 587 struct drm_mode_mode_cmd res; 588 589 memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); 590 res.connector_id = connector_id; 591 592 return DRM_IOCTL(fd, DRM_IOCTL_MODE_DETACHMODE, &res); 593} 594 595 596drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) 597{ 598 struct drm_mode_get_property prop; 599 drmModePropertyPtr r; 600 601 VG_CLEAR(prop); 602 prop.prop_id = property_id; 603 prop.count_enum_blobs = 0; 604 prop.count_values = 0; 605 prop.flags = 0; 606 prop.enum_blob_ptr = 0; 607 prop.values_ptr = 0; 608 609 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) 610 return 0; 611 612 if (prop.count_values) 613 prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t))); 614 615 if (prop.count_enum_blobs && (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK))) 616 prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum))); 617 618 if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) { 619 prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); 620 prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); 621 } 622 623 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) { 624 r = NULL; 625 goto err_allocs; 626 } 627 628 if (!(r = drmMalloc(sizeof(*r)))) 629 return NULL; 630 631 r->prop_id = prop.prop_id; 632 r->count_values = prop.count_values; 633 634 r->flags = prop.flags; 635 if (prop.count_values) 636 r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t)); 637 if (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { 638 r->count_enums = prop.count_enum_blobs; 639 r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum)); 640 } else if (prop.flags & DRM_MODE_PROP_BLOB) { 641 r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t)); 642 r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t)); 643 r->count_blobs = prop.count_enum_blobs; 644 } 645 strncpy(r->name, prop.name, DRM_PROP_NAME_LEN); 646 r->name[DRM_PROP_NAME_LEN-1] = 0; 647 648err_allocs: 649 drmFree(U642VOID(prop.values_ptr)); 650 drmFree(U642VOID(prop.enum_blob_ptr)); 651 652 return r; 653} 654 655void drmModeFreeProperty(drmModePropertyPtr ptr) 656{ 657 if (!ptr) 658 return; 659 660 drmFree(ptr->values); 661 drmFree(ptr->enums); 662 drmFree(ptr); 663} 664 665drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id) 666{ 667 struct drm_mode_get_blob blob; 668 drmModePropertyBlobPtr r; 669 670 blob.length = 0; 671 blob.data = 0; 672 blob.blob_id = blob_id; 673 674 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) 675 return NULL; 676 677 if (blob.length) 678 blob.data = VOID2U64(drmMalloc(blob.length)); 679 680 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) { 681 r = NULL; 682 goto err_allocs; 683 } 684 685 if (!(r = drmMalloc(sizeof(*r)))) 686 goto err_allocs; 687 688 r->id = blob.blob_id; 689 r->length = blob.length; 690 r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length); 691 692err_allocs: 693 drmFree(U642VOID(blob.data)); 694 return r; 695} 696 697void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr) 698{ 699 if (!ptr) 700 return; 701 702 drmFree(ptr->data); 703 drmFree(ptr); 704} 705 706int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id, 707 uint64_t value) 708{ 709 struct drm_mode_connector_set_property osp; 710 711 osp.connector_id = connector_id; 712 osp.prop_id = property_id; 713 osp.value = value; 714 715 return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp); 716} 717 718/* 719 * checks if a modesetting capable driver has attached to the pci id 720 * returns 0 if modesetting supported. 721 * -EINVAL or invalid bus id 722 * -ENOSYS if no modesetting support 723*/ 724int drmCheckModesettingSupported(const char *busid) 725{ 726#ifdef __linux__ 727 char pci_dev_dir[1024]; 728 int domain, bus, dev, func; 729 DIR *sysdir; 730 struct dirent *dent; 731 int found = 0, ret; 732 733 ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func); 734 if (ret != 4) 735 return -EINVAL; 736 737 sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm", 738 domain, bus, dev, func); 739 740 sysdir = opendir(pci_dev_dir); 741 if (sysdir) { 742 dent = readdir(sysdir); 743 while (dent) { 744 if (!strncmp(dent->d_name, "controlD", 8)) { 745 found = 1; 746 break; 747 } 748 749 dent = readdir(sysdir); 750 } 751 closedir(sysdir); 752 if (found) 753 return 0; 754 } 755 756 sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/", 757 domain, bus, dev, func); 758 759 sysdir = opendir(pci_dev_dir); 760 if (!sysdir) 761 return -EINVAL; 762 763 dent = readdir(sysdir); 764 while (dent) { 765 if (!strncmp(dent->d_name, "drm:controlD", 12)) { 766 found = 1; 767 break; 768 } 769 770 dent = readdir(sysdir); 771 } 772 773 closedir(sysdir); 774 if (found) 775 return 0; 776#endif 777#ifdef __NetBSD__ 778 int fd; 779 static const struct drm_mode_card_res zero_res; 780 struct drm_mode_card_res res = zero_res; 781 int ret; 782 783 fd = drmOpen(NULL, busid); 784 if (fd == -1) 785 return -EINVAL; 786 if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) 787 ret = -errno; 788 else 789 ret = 0; 790 drmClose(fd); 791 return ret; 792#endif 793 return -ENOSYS; 794 795} 796 797int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, 798 uint16_t *red, uint16_t *green, uint16_t *blue) 799{ 800 struct drm_mode_crtc_lut l; 801 802 l.crtc_id = crtc_id; 803 l.gamma_size = size; 804 l.red = VOID2U64(red); 805 l.green = VOID2U64(green); 806 l.blue = VOID2U64(blue); 807 808 return DRM_IOCTL(fd, DRM_IOCTL_MODE_GETGAMMA, &l); 809} 810 811int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, 812 uint16_t *red, uint16_t *green, uint16_t *blue) 813{ 814 struct drm_mode_crtc_lut l; 815 816 l.crtc_id = crtc_id; 817 l.gamma_size = size; 818 l.red = VOID2U64(red); 819 l.green = VOID2U64(green); 820 l.blue = VOID2U64(blue); 821 822 return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l); 823} 824 825int drmHandleEvent(int fd, drmEventContextPtr evctx) 826{ 827 char buffer[1024]; 828 int len, i; 829 struct drm_event *e; 830 struct drm_event_vblank *vblank; 831 832 /* The DRM read semantics guarantees that we always get only 833 * complete events. */ 834 835 len = read(fd, buffer, sizeof buffer); 836 if (len == 0) 837 return 0; 838 if (len < sizeof *e) 839 return -1; 840 841 i = 0; 842 while (i < len) { 843 e = (struct drm_event *) &buffer[i]; 844 switch (e->type) { 845 case DRM_EVENT_VBLANK: 846 if (evctx->version < 1 || 847 evctx->vblank_handler == NULL) 848 break; 849 vblank = (struct drm_event_vblank *) e; 850 evctx->vblank_handler(fd, 851 vblank->sequence, 852 vblank->tv_sec, 853 vblank->tv_usec, 854 U642VOID (vblank->user_data)); 855 break; 856 case DRM_EVENT_FLIP_COMPLETE: 857 if (evctx->version < 2 || 858 evctx->page_flip_handler == NULL) 859 break; 860 vblank = (struct drm_event_vblank *) e; 861 evctx->page_flip_handler(fd, 862 vblank->sequence, 863 vblank->tv_sec, 864 vblank->tv_usec, 865 U642VOID (vblank->user_data)); 866 break; 867 default: 868 break; 869 } 870 i += e->length; 871 } 872 873 return 0; 874} 875 876int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, 877 uint32_t flags, void *user_data) 878{ 879 struct drm_mode_crtc_page_flip flip; 880 881 flip.fb_id = fb_id; 882 flip.crtc_id = crtc_id; 883 flip.user_data = VOID2U64(user_data); 884 flip.flags = flags; 885 flip.reserved = 0; 886 887 return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip); 888} 889 890int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, 891 uint32_t fb_id, uint32_t flags, 892 uint32_t crtc_x, uint32_t crtc_y, 893 uint32_t crtc_w, uint32_t crtc_h, 894 uint32_t src_x, uint32_t src_y, 895 uint32_t src_w, uint32_t src_h) 896 897{ 898 struct drm_mode_set_plane s; 899 900 s.plane_id = plane_id; 901 s.crtc_id = crtc_id; 902 s.fb_id = fb_id; 903 s.flags = flags; 904 s.crtc_x = crtc_x; 905 s.crtc_y = crtc_y; 906 s.crtc_w = crtc_w; 907 s.crtc_h = crtc_h; 908 s.src_x = src_x; 909 s.src_y = src_y; 910 s.src_w = src_w; 911 s.src_h = src_h; 912 913 return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPLANE, &s); 914} 915 916 917drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id) 918{ 919 struct drm_mode_get_plane ovr, counts; 920 drmModePlanePtr r = 0; 921 922retry: 923 memset(&ovr, 0, sizeof(struct drm_mode_get_plane)); 924 ovr.plane_id = plane_id; 925 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr)) 926 return 0; 927 928 counts = ovr; 929 930 if (ovr.count_format_types) { 931 ovr.format_type_ptr = VOID2U64(drmMalloc(ovr.count_format_types * 932 sizeof(uint32_t))); 933 if (!ovr.format_type_ptr) 934 goto err_allocs; 935 } 936 937 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr)) 938 goto err_allocs; 939 940 if (counts.count_format_types < ovr.count_format_types) { 941 drmFree(U642VOID(ovr.format_type_ptr)); 942 goto retry; 943 } 944 945 if (!(r = drmMalloc(sizeof(*r)))) 946 goto err_allocs; 947 948 r->count_formats = ovr.count_format_types; 949 r->plane_id = ovr.plane_id; 950 r->crtc_id = ovr.crtc_id; 951 r->fb_id = ovr.fb_id; 952 r->possible_crtcs = ovr.possible_crtcs; 953 r->gamma_size = ovr.gamma_size; 954 r->formats = drmAllocCpy(U642VOID(ovr.format_type_ptr), 955 ovr.count_format_types, sizeof(uint32_t)); 956 if (ovr.count_format_types && !r->formats) { 957 drmFree(r->formats); 958 drmFree(r); 959 r = 0; 960 } 961 962err_allocs: 963 drmFree(U642VOID(ovr.format_type_ptr)); 964 965 return r; 966} 967 968void drmModeFreePlane(drmModePlanePtr ptr) 969{ 970 if (!ptr) 971 return; 972 973 drmFree(ptr->formats); 974 drmFree(ptr); 975} 976 977drmModePlaneResPtr drmModeGetPlaneResources(int fd) 978{ 979 struct drm_mode_get_plane_res res, counts; 980 drmModePlaneResPtr r = 0; 981 982retry: 983 memset(&res, 0, sizeof(struct drm_mode_get_plane_res)); 984 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res)) 985 return 0; 986 987 counts = res; 988 989 if (res.count_planes) { 990 res.plane_id_ptr = VOID2U64(drmMalloc(res.count_planes * 991 sizeof(uint32_t))); 992 if (!res.plane_id_ptr) 993 goto err_allocs; 994 } 995 996 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res)) 997 goto err_allocs; 998 999 if (counts.count_planes < res.count_planes) { 1000 drmFree(U642VOID(res.plane_id_ptr)); 1001 goto retry; 1002 } 1003 1004 if (!(r = drmMalloc(sizeof(*r)))) 1005 goto err_allocs; 1006 1007 r->count_planes = res.count_planes; 1008 r->planes = drmAllocCpy(U642VOID(res.plane_id_ptr), 1009 res.count_planes, sizeof(uint32_t)); 1010 if (res.count_planes && !r->planes) { 1011 drmFree(r->planes); 1012 drmFree(r); 1013 r = 0; 1014 } 1015 1016err_allocs: 1017 drmFree(U642VOID(res.plane_id_ptr)); 1018 1019 return r; 1020} 1021 1022void drmModeFreePlaneResources(drmModePlaneResPtr ptr) 1023{ 1024 if (!ptr) 1025 return; 1026 1027 drmFree(ptr->planes); 1028 drmFree(ptr); 1029} 1030 1031drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, 1032 uint32_t object_id, 1033 uint32_t object_type) 1034{ 1035 struct drm_mode_obj_get_properties properties; 1036 drmModeObjectPropertiesPtr ret = NULL; 1037 uint32_t count; 1038 1039retry: 1040 memset(&properties, 0, sizeof(struct drm_mode_obj_get_properties)); 1041 properties.obj_id = object_id; 1042 properties.obj_type = object_type; 1043 1044 if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)) 1045 return 0; 1046 1047 count = properties.count_props; 1048 1049 if (count) { 1050 properties.props_ptr = VOID2U64(drmMalloc(count * 1051 sizeof(uint32_t))); 1052 if (!properties.props_ptr) 1053 goto err_allocs; 1054 properties.prop_values_ptr = VOID2U64(drmMalloc(count * 1055 sizeof(uint64_t))); 1056 if (!properties.prop_values_ptr) 1057 goto err_allocs; 1058 } 1059 1060 if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)) 1061 goto err_allocs; 1062 1063 if (count < properties.count_props) { 1064 drmFree(U642VOID(properties.props_ptr)); 1065 drmFree(U642VOID(properties.prop_values_ptr)); 1066 goto retry; 1067 } 1068 count = properties.count_props; 1069 1070 ret = drmMalloc(sizeof(*ret)); 1071 if (!ret) 1072 goto err_allocs; 1073 1074 ret->count_props = count; 1075 ret->props = drmAllocCpy(U642VOID(properties.props_ptr), 1076 count, sizeof(uint32_t)); 1077 ret->prop_values = drmAllocCpy(U642VOID(properties.prop_values_ptr), 1078 count, sizeof(uint64_t)); 1079 if (ret->count_props && (!ret->props || !ret->prop_values)) { 1080 drmFree(ret->props); 1081 drmFree(ret->prop_values); 1082 drmFree(ret); 1083 ret = NULL; 1084 } 1085 1086err_allocs: 1087 drmFree(U642VOID(properties.props_ptr)); 1088 drmFree(U642VOID(properties.prop_values_ptr)); 1089 return ret; 1090} 1091 1092void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr) 1093{ 1094 if (!ptr) 1095 return; 1096 drmFree(ptr->props); 1097 drmFree(ptr->prop_values); 1098 drmFree(ptr); 1099} 1100 1101int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type, 1102 uint32_t property_id, uint64_t value) 1103{ 1104 struct drm_mode_obj_set_property prop; 1105 1106 prop.value = value; 1107 prop.prop_id = property_id; 1108 prop.obj_id = object_id; 1109 prop.obj_type = object_type; 1110 1111 return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop); 1112} 1113