xf86drmMode.c revision e05f3551
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#if defined (__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#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) 777 char kbusid[1024], sbusid[1024]; 778 char oid[128]; 779 int domain, bus, dev, func; 780 int i, modesetting, ret; 781 size_t len; 782 783 ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, 784 &func); 785 if (ret != 4) 786 return -EINVAL; 787 snprintf(kbusid, sizeof(kbusid), "pci:%04x:%02x:%02x.%d", domain, bus, 788 dev, func); 789 790 /* How many GPUs do we expect in the machine ? */ 791 for (i = 0; i < 16; i++) { 792 snprintf(oid, sizeof(oid), "hw.dri.%d.busid", i); 793 len = sizeof(sbusid); 794 ret = sysctlbyname(oid, sbusid, &len, NULL, 0); 795 if (ret == -1) { 796 if (errno == ENOENT) 797 continue; 798 return -EINVAL; 799 } 800 if (strcmp(sbusid, kbusid) != 0) 801 continue; 802 snprintf(oid, sizeof(oid), "hw.dri.%d.modesetting", i); 803 len = sizeof(modesetting); 804 ret = sysctlbyname(oid, &modesetting, &len, NULL, 0); 805 if (ret == -1 || len != sizeof(modesetting)) 806 return -EINVAL; 807 return (modesetting ? 0 : -ENOSYS); 808 } 809#elif defined(__DragonFly__) 810 return 0; 811#else 812 int fd; 813 static const struct drm_mode_card_res zero_res; 814 struct drm_mode_card_res res = zero_res; 815 int ret; 816 817 fd = drmOpen(NULL, busid); 818 if (fd == -1) 819 return -EINVAL; 820 ret = drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res); 821 drmClose(fd); 822 if (ret == 0) 823 return 0; 824#endif 825 return -ENOSYS; 826 827} 828 829int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, 830 uint16_t *red, uint16_t *green, uint16_t *blue) 831{ 832 struct drm_mode_crtc_lut l; 833 834 l.crtc_id = crtc_id; 835 l.gamma_size = size; 836 l.red = VOID2U64(red); 837 l.green = VOID2U64(green); 838 l.blue = VOID2U64(blue); 839 840 return DRM_IOCTL(fd, DRM_IOCTL_MODE_GETGAMMA, &l); 841} 842 843int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, 844 uint16_t *red, uint16_t *green, uint16_t *blue) 845{ 846 struct drm_mode_crtc_lut l; 847 848 l.crtc_id = crtc_id; 849 l.gamma_size = size; 850 l.red = VOID2U64(red); 851 l.green = VOID2U64(green); 852 l.blue = VOID2U64(blue); 853 854 return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l); 855} 856 857int drmHandleEvent(int fd, drmEventContextPtr evctx) 858{ 859 char buffer[1024]; 860 int len, i; 861 struct drm_event *e; 862 struct drm_event_vblank *vblank; 863 864 /* The DRM read semantics guarantees that we always get only 865 * complete events. */ 866 867 len = read(fd, buffer, sizeof buffer); 868 if (len == 0) 869 return 0; 870 if (len < sizeof *e) 871 return -1; 872 873 i = 0; 874 while (i < len) { 875 e = (struct drm_event *) &buffer[i]; 876 switch (e->type) { 877 case DRM_EVENT_VBLANK: 878 if (evctx->version < 1 || 879 evctx->vblank_handler == NULL) 880 break; 881 vblank = (struct drm_event_vblank *) e; 882 evctx->vblank_handler(fd, 883 vblank->sequence, 884 vblank->tv_sec, 885 vblank->tv_usec, 886 U642VOID (vblank->user_data)); 887 break; 888 case DRM_EVENT_FLIP_COMPLETE: 889 if (evctx->version < 2 || 890 evctx->page_flip_handler == NULL) 891 break; 892 vblank = (struct drm_event_vblank *) e; 893 evctx->page_flip_handler(fd, 894 vblank->sequence, 895 vblank->tv_sec, 896 vblank->tv_usec, 897 U642VOID (vblank->user_data)); 898 break; 899 default: 900 break; 901 } 902 i += e->length; 903 } 904 905 return 0; 906} 907 908int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, 909 uint32_t flags, void *user_data) 910{ 911 struct drm_mode_crtc_page_flip flip; 912 913 flip.fb_id = fb_id; 914 flip.crtc_id = crtc_id; 915 flip.user_data = VOID2U64(user_data); 916 flip.flags = flags; 917 flip.reserved = 0; 918 919 return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip); 920} 921 922int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, 923 uint32_t fb_id, uint32_t flags, 924 uint32_t crtc_x, uint32_t crtc_y, 925 uint32_t crtc_w, uint32_t crtc_h, 926 uint32_t src_x, uint32_t src_y, 927 uint32_t src_w, uint32_t src_h) 928 929{ 930 struct drm_mode_set_plane s; 931 932 s.plane_id = plane_id; 933 s.crtc_id = crtc_id; 934 s.fb_id = fb_id; 935 s.flags = flags; 936 s.crtc_x = crtc_x; 937 s.crtc_y = crtc_y; 938 s.crtc_w = crtc_w; 939 s.crtc_h = crtc_h; 940 s.src_x = src_x; 941 s.src_y = src_y; 942 s.src_w = src_w; 943 s.src_h = src_h; 944 945 return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPLANE, &s); 946} 947 948 949drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id) 950{ 951 struct drm_mode_get_plane ovr, counts; 952 drmModePlanePtr r = 0; 953 954retry: 955 memset(&ovr, 0, sizeof(struct drm_mode_get_plane)); 956 ovr.plane_id = plane_id; 957 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr)) 958 return 0; 959 960 counts = ovr; 961 962 if (ovr.count_format_types) { 963 ovr.format_type_ptr = VOID2U64(drmMalloc(ovr.count_format_types * 964 sizeof(uint32_t))); 965 if (!ovr.format_type_ptr) 966 goto err_allocs; 967 } 968 969 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr)) 970 goto err_allocs; 971 972 if (counts.count_format_types < ovr.count_format_types) { 973 drmFree(U642VOID(ovr.format_type_ptr)); 974 goto retry; 975 } 976 977 if (!(r = drmMalloc(sizeof(*r)))) 978 goto err_allocs; 979 980 r->count_formats = ovr.count_format_types; 981 r->plane_id = ovr.plane_id; 982 r->crtc_id = ovr.crtc_id; 983 r->fb_id = ovr.fb_id; 984 r->possible_crtcs = ovr.possible_crtcs; 985 r->gamma_size = ovr.gamma_size; 986 r->formats = drmAllocCpy(U642VOID(ovr.format_type_ptr), 987 ovr.count_format_types, sizeof(uint32_t)); 988 if (ovr.count_format_types && !r->formats) { 989 drmFree(r->formats); 990 drmFree(r); 991 r = 0; 992 } 993 994err_allocs: 995 drmFree(U642VOID(ovr.format_type_ptr)); 996 997 return r; 998} 999 1000void drmModeFreePlane(drmModePlanePtr ptr) 1001{ 1002 if (!ptr) 1003 return; 1004 1005 drmFree(ptr->formats); 1006 drmFree(ptr); 1007} 1008 1009drmModePlaneResPtr drmModeGetPlaneResources(int fd) 1010{ 1011 struct drm_mode_get_plane_res res, counts; 1012 drmModePlaneResPtr r = 0; 1013 1014retry: 1015 memset(&res, 0, sizeof(struct drm_mode_get_plane_res)); 1016 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res)) 1017 return 0; 1018 1019 counts = res; 1020 1021 if (res.count_planes) { 1022 res.plane_id_ptr = VOID2U64(drmMalloc(res.count_planes * 1023 sizeof(uint32_t))); 1024 if (!res.plane_id_ptr) 1025 goto err_allocs; 1026 } 1027 1028 if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res)) 1029 goto err_allocs; 1030 1031 if (counts.count_planes < res.count_planes) { 1032 drmFree(U642VOID(res.plane_id_ptr)); 1033 goto retry; 1034 } 1035 1036 if (!(r = drmMalloc(sizeof(*r)))) 1037 goto err_allocs; 1038 1039 r->count_planes = res.count_planes; 1040 r->planes = drmAllocCpy(U642VOID(res.plane_id_ptr), 1041 res.count_planes, sizeof(uint32_t)); 1042 if (res.count_planes && !r->planes) { 1043 drmFree(r->planes); 1044 drmFree(r); 1045 r = 0; 1046 } 1047 1048err_allocs: 1049 drmFree(U642VOID(res.plane_id_ptr)); 1050 1051 return r; 1052} 1053 1054void drmModeFreePlaneResources(drmModePlaneResPtr ptr) 1055{ 1056 if (!ptr) 1057 return; 1058 1059 drmFree(ptr->planes); 1060 drmFree(ptr); 1061} 1062 1063drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, 1064 uint32_t object_id, 1065 uint32_t object_type) 1066{ 1067 struct drm_mode_obj_get_properties properties; 1068 drmModeObjectPropertiesPtr ret = NULL; 1069 uint32_t count; 1070 1071retry: 1072 memset(&properties, 0, sizeof(struct drm_mode_obj_get_properties)); 1073 properties.obj_id = object_id; 1074 properties.obj_type = object_type; 1075 1076 if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)) 1077 return 0; 1078 1079 count = properties.count_props; 1080 1081 if (count) { 1082 properties.props_ptr = VOID2U64(drmMalloc(count * 1083 sizeof(uint32_t))); 1084 if (!properties.props_ptr) 1085 goto err_allocs; 1086 properties.prop_values_ptr = VOID2U64(drmMalloc(count * 1087 sizeof(uint64_t))); 1088 if (!properties.prop_values_ptr) 1089 goto err_allocs; 1090 } 1091 1092 if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)) 1093 goto err_allocs; 1094 1095 if (count < properties.count_props) { 1096 drmFree(U642VOID(properties.props_ptr)); 1097 drmFree(U642VOID(properties.prop_values_ptr)); 1098 goto retry; 1099 } 1100 count = properties.count_props; 1101 1102 ret = drmMalloc(sizeof(*ret)); 1103 if (!ret) 1104 goto err_allocs; 1105 1106 ret->count_props = count; 1107 ret->props = drmAllocCpy(U642VOID(properties.props_ptr), 1108 count, sizeof(uint32_t)); 1109 ret->prop_values = drmAllocCpy(U642VOID(properties.prop_values_ptr), 1110 count, sizeof(uint64_t)); 1111 if (ret->count_props && (!ret->props || !ret->prop_values)) { 1112 drmFree(ret->props); 1113 drmFree(ret->prop_values); 1114 drmFree(ret); 1115 ret = NULL; 1116 } 1117 1118err_allocs: 1119 drmFree(U642VOID(properties.props_ptr)); 1120 drmFree(U642VOID(properties.prop_values_ptr)); 1121 return ret; 1122} 1123 1124void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr) 1125{ 1126 if (!ptr) 1127 return; 1128 drmFree(ptr->props); 1129 drmFree(ptr->prop_values); 1130 drmFree(ptr); 1131} 1132 1133int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type, 1134 uint32_t property_id, uint64_t value) 1135{ 1136 struct drm_mode_obj_set_property prop; 1137 1138 prop.value = value; 1139 prop.prop_id = property_id; 1140 prop.obj_id = object_id; 1141 prop.obj_type = object_type; 1142 1143 return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop); 1144} 1145