~ubuntu-branches/ubuntu/maverick/libdrm/maverick-proposed

« back to all changes in this revision

Viewing changes to xf86drmMode.c

  • Committer: Bazaar Package Importer
  • Author(s): Timo Aaltonen
  • Date: 2010-01-09 00:00:29 UTC
  • mfrom: (1.3.3 upstream)
  • mto: (2.2.9 experimental)
  • mto: This revision was merged to the branch mainline in revision 39.
  • Revision ID: james.westby@ubuntu.com-20100109000029-yhmol07llcxuzk0c
Tags: upstream-2.4.17
ImportĀ upstreamĀ versionĀ 2.4.17

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#include "xf86drmMode.h"
 
45
#include "xf86drm.h"
 
46
#include <drm.h>
 
47
#include <string.h>
 
48
#include <dirent.h>
 
49
#include <unistd.h>
 
50
#include <errno.h>
 
51
 
 
52
#define U642VOID(x) ((void *)(unsigned long)(x))
 
53
#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
 
54
 
 
55
/*
 
56
 * Util functions
 
57
 */
 
58
 
 
59
void* drmAllocCpy(void *array, int count, int entry_size)
 
60
{
 
61
        char *r;
 
62
        int i;
 
63
 
 
64
        if (!count || !array || !entry_size)
 
65
                return 0;
 
66
 
 
67
        if (!(r = drmMalloc(count*entry_size)))
 
68
                return 0;
 
69
 
 
70
        for (i = 0; i < count; i++)
 
71
                memcpy(r+(entry_size*i), array+(entry_size*i), entry_size);
 
72
 
 
73
        return r;
 
74
}
 
75
 
 
76
/*
 
77
 * A couple of free functions.
 
78
 */
 
79
 
 
80
void drmModeFreeModeInfo(drmModeModeInfoPtr ptr)
 
81
{
 
82
        if (!ptr)
 
83
                return;
 
84
 
 
85
        drmFree(ptr);
 
86
}
 
87
 
 
88
void drmModeFreeResources(drmModeResPtr ptr)
 
89
{
 
90
        if (!ptr)
 
91
                return;
 
92
 
 
93
        drmFree(ptr);
 
94
 
 
95
}
 
96
 
 
97
void drmModeFreeFB(drmModeFBPtr ptr)
 
98
{
 
99
        if (!ptr)
 
100
                return;
 
101
 
 
102
        /* we might add more frees later. */
 
103
        drmFree(ptr);
 
104
}
 
105
 
 
106
void drmModeFreeCrtc(drmModeCrtcPtr ptr)
 
107
{
 
108
        if (!ptr)
 
109
                return;
 
110
 
 
111
        drmFree(ptr);
 
112
 
 
113
}
 
114
 
 
115
void drmModeFreeConnector(drmModeConnectorPtr ptr)
 
116
{
 
117
        if (!ptr)
 
118
                return;
 
119
 
 
120
        drmFree(ptr->encoders);
 
121
        drmFree(ptr->prop_values);
 
122
        drmFree(ptr->props);
 
123
        drmFree(ptr->modes);
 
124
        drmFree(ptr);
 
125
 
 
126
}
 
127
 
 
128
void drmModeFreeEncoder(drmModeEncoderPtr ptr)
 
129
{
 
130
        drmFree(ptr);
 
131
}
 
132
 
 
133
/*
 
134
 * ModeSetting functions.
 
135
 */
 
136
 
 
137
drmModeResPtr drmModeGetResources(int fd)
 
138
{
 
139
        struct drm_mode_card_res res;
 
140
        drmModeResPtr r = 0;
 
141
 
 
142
        memset(&res, 0, sizeof(struct drm_mode_card_res));
 
143
 
 
144
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
 
145
                return 0;
 
146
 
 
147
        if (res.count_fbs)
 
148
                res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t)));
 
149
        if (res.count_crtcs)
 
150
                res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t)));
 
151
        if (res.count_connectors)
 
152
                res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t)));
 
153
        if (res.count_encoders)
 
154
                res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t)));
 
155
 
 
156
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) {
 
157
                r = NULL;
 
158
                goto err_allocs;
 
159
        }
 
160
 
 
161
        /*
 
162
         * return
 
163
         */
 
164
 
 
165
 
 
166
        if (!(r = drmMalloc(sizeof(*r))))
 
167
                return 0;
 
168
 
 
169
        r->min_width     = res.min_width;
 
170
        r->max_width     = res.max_width;
 
171
        r->min_height    = res.min_height;
 
172
        r->max_height    = res.max_height;
 
173
        r->count_fbs     = res.count_fbs;
 
174
        r->count_crtcs   = res.count_crtcs;
 
175
        r->count_connectors = res.count_connectors;
 
176
        r->count_encoders = res.count_encoders;
 
177
        /* TODO we realy should test if these allocs fails. */
 
178
        r->fbs           = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t));
 
179
        r->crtcs         = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t));
 
180
        r->connectors       = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t));
 
181
        r->encoders      = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t));
 
182
 
 
183
err_allocs:
 
184
        drmFree(U642VOID(res.fb_id_ptr));
 
185
        drmFree(U642VOID(res.crtc_id_ptr));
 
186
        drmFree(U642VOID(res.connector_id_ptr));
 
187
        drmFree(U642VOID(res.encoder_id_ptr));
 
188
 
 
189
        return r;
 
190
}
 
191
 
 
192
int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
 
193
                 uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
 
194
                 uint32_t *buf_id)
 
195
{
 
196
        struct drm_mode_fb_cmd f;
 
197
        int ret;
 
198
 
 
199
        f.width  = width;
 
200
        f.height = height;
 
201
        f.pitch  = pitch;
 
202
        f.bpp    = bpp;
 
203
        f.depth  = depth;
 
204
        f.handle = bo_handle;
 
205
 
 
206
        if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB, &f)))
 
207
                return ret;
 
208
 
 
209
        *buf_id = f.fb_id;
 
210
        return 0;
 
211
}
 
212
 
 
213
int drmModeRmFB(int fd, uint32_t bufferId)
 
214
{
 
215
        return drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
 
216
 
 
217
 
 
218
}
 
219
 
 
220
drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
 
221
{
 
222
        struct drm_mode_fb_cmd info;
 
223
        drmModeFBPtr r;
 
224
 
 
225
        info.fb_id = buf;
 
226
 
 
227
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info))
 
228
                return NULL;
 
229
 
 
230
        if (!(r = drmMalloc(sizeof(*r))))
 
231
                return NULL;
 
232
 
 
233
        r->fb_id = info.fb_id;
 
234
        r->width = info.width;
 
235
        r->height = info.height;
 
236
        r->pitch = info.pitch;
 
237
        r->bpp = info.bpp;
 
238
        r->handle = info.handle;
 
239
        r->depth = info.depth;
 
240
 
 
241
        return r;
 
242
}
 
243
 
 
244
int drmModeDirtyFB(int fd, uint32_t bufferId,
 
245
                   drmModeClipPtr clips, uint32_t num_clips)
 
246
{
 
247
        struct drm_mode_fb_dirty_cmd dirty = { 0 };
 
248
 
 
249
        dirty.fb_id = bufferId;
 
250
        dirty.clips_ptr = VOID2U64(clips);
 
251
        dirty.num_clips = num_clips;
 
252
 
 
253
        return drmIoctl(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty);
 
254
}
 
255
 
 
256
 
 
257
/*
 
258
 * Crtc functions
 
259
 */
 
260
 
 
261
drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
 
262
{
 
263
        struct drm_mode_crtc crtc;
 
264
        drmModeCrtcPtr r;
 
265
 
 
266
        crtc.crtc_id = crtcId;
 
267
 
 
268
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
 
269
                return 0;
 
270
 
 
271
        /*
 
272
         * return
 
273
         */
 
274
 
 
275
        if (!(r = drmMalloc(sizeof(*r))))
 
276
                return 0;
 
277
 
 
278
        r->crtc_id         = crtc.crtc_id;
 
279
        r->x               = crtc.x;
 
280
        r->y               = crtc.y;
 
281
        r->mode_valid      = crtc.mode_valid;
 
282
        if (r->mode_valid)
 
283
                memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));
 
284
        r->buffer_id       = crtc.fb_id;
 
285
        r->gamma_size      = crtc.gamma_size;
 
286
        return r;
 
287
}
 
288
 
 
289
 
 
290
int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
 
291
                   uint32_t x, uint32_t y, uint32_t *connectors, int count,
 
292
                   drmModeModeInfoPtr mode)
 
293
{
 
294
        struct drm_mode_crtc crtc;
 
295
 
 
296
        crtc.x             = x;
 
297
        crtc.y             = y;
 
298
        crtc.crtc_id       = crtcId;
 
299
        crtc.fb_id         = bufferId;
 
300
        crtc.set_connectors_ptr = VOID2U64(connectors);
 
301
        crtc.count_connectors = count;
 
302
        if (mode) {
 
303
          memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
 
304
          crtc.mode_valid = 1;
 
305
        } else
 
306
          crtc.mode_valid = 0;
 
307
 
 
308
        return drmIoctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
 
309
}
 
310
 
 
311
/*
 
312
 * Cursor manipulation
 
313
 */
 
314
 
 
315
int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height)
 
316
{
 
317
        struct drm_mode_cursor arg;
 
318
 
 
319
        arg.flags = DRM_MODE_CURSOR_BO;
 
320
        arg.crtc_id = crtcId;
 
321
        arg.width = width;
 
322
        arg.height = height;
 
323
        arg.handle = bo_handle;
 
324
 
 
325
        return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
 
326
}
 
327
 
 
328
int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
 
329
{
 
330
        struct drm_mode_cursor arg;
 
331
 
 
332
        arg.flags = DRM_MODE_CURSOR_MOVE;
 
333
        arg.crtc_id = crtcId;
 
334
        arg.x = x;
 
335
        arg.y = y;
 
336
 
 
337
        return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
 
338
}
 
339
 
 
340
/*
 
341
 * Encoder get
 
342
 */
 
343
drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
 
344
{
 
345
        struct drm_mode_get_encoder enc;
 
346
        drmModeEncoderPtr r = NULL;
 
347
 
 
348
        enc.encoder_id = encoder_id;
 
349
        enc.encoder_type = 0;
 
350
        enc.possible_crtcs = 0;
 
351
        enc.possible_clones = 0;
 
352
 
 
353
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc))
 
354
                return 0;
 
355
 
 
356
        if (!(r = drmMalloc(sizeof(*r))))
 
357
                return 0;
 
358
 
 
359
        r->encoder_id = enc.encoder_id;
 
360
        r->crtc_id = enc.crtc_id;
 
361
        r->encoder_type = enc.encoder_type;
 
362
        r->possible_crtcs = enc.possible_crtcs;
 
363
        r->possible_clones = enc.possible_clones;
 
364
 
 
365
        return r;
 
366
}
 
367
 
 
368
/*
 
369
 * Connector manipulation
 
370
 */
 
371
 
 
372
drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
 
373
{
 
374
        struct drm_mode_get_connector conn;
 
375
        drmModeConnectorPtr r = NULL;
 
376
 
 
377
        conn.connector_id = connector_id;
 
378
        conn.connector_type_id = 0;
 
379
        conn.connector_type  = 0;
 
380
        conn.count_modes  = 0;
 
381
        conn.modes_ptr    = 0;
 
382
        conn.count_props  = 0;
 
383
        conn.props_ptr    = 0;
 
384
        conn.prop_values_ptr = 0;
 
385
        conn.count_encoders  = 0;
 
386
        conn.encoders_ptr = 0;
 
387
 
 
388
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
 
389
                return 0;
 
390
 
 
391
        if (conn.count_props) {
 
392
                conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
 
393
                conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
 
394
        }
 
395
 
 
396
        if (conn.count_modes)
 
397
                conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));
 
398
 
 
399
        if (conn.count_encoders)
 
400
                conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));
 
401
 
 
402
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
 
403
                goto err_allocs;
 
404
 
 
405
        if(!(r = drmMalloc(sizeof(*r)))) {
 
406
                goto err_allocs;
 
407
        }
 
408
 
 
409
        r->connector_id = conn.connector_id;
 
410
        r->encoder_id = conn.encoder_id;
 
411
        r->connection   = conn.connection;
 
412
        r->mmWidth      = conn.mm_width;
 
413
        r->mmHeight     = conn.mm_height;
 
414
        /* convert subpixel from kernel to userspace */
 
415
        r->subpixel     = conn.subpixel + 1;
 
416
        r->count_modes  = conn.count_modes;
 
417
        /* TODO we should test if these alloc & cpy fails. */
 
418
        r->count_props  = conn.count_props;
 
419
        r->props        = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));
 
420
        r->prop_values  = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));
 
421
        r->modes        = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo));
 
422
        r->count_encoders = conn.count_encoders;
 
423
        r->encoders     = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t));
 
424
        r->connector_type  = conn.connector_type;
 
425
        r->connector_type_id = conn.connector_type_id;
 
426
 
 
427
        if (!r->props || !r->prop_values || !r->modes || !r->encoders)
 
428
                goto err_allocs;
 
429
 
 
430
err_allocs:
 
431
        drmFree(U642VOID(conn.prop_values_ptr));
 
432
        drmFree(U642VOID(conn.props_ptr));
 
433
        drmFree(U642VOID(conn.modes_ptr));
 
434
        drmFree(U642VOID(conn.encoders_ptr));
 
435
 
 
436
        return r;
 
437
}
 
438
 
 
439
int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
 
440
{
 
441
        struct drm_mode_mode_cmd res;
 
442
 
 
443
        memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
 
444
        res.connector_id = connector_id;
 
445
 
 
446
        return drmIoctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
 
447
}
 
448
 
 
449
int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
 
450
{
 
451
        struct drm_mode_mode_cmd res;
 
452
 
 
453
        memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
 
454
        res.connector_id = connector_id;
 
455
 
 
456
        return drmIoctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
 
457
}
 
458
 
 
459
 
 
460
drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
 
461
{
 
462
        struct drm_mode_get_property prop;
 
463
        drmModePropertyPtr r;
 
464
 
 
465
        prop.prop_id = property_id;
 
466
        prop.count_enum_blobs = 0;
 
467
        prop.count_values = 0;
 
468
        prop.flags = 0;
 
469
        prop.enum_blob_ptr = 0;
 
470
        prop.values_ptr = 0;
 
471
 
 
472
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
 
473
                return 0;
 
474
 
 
475
        if (prop.count_values)
 
476
                prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t)));
 
477
 
 
478
        if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM))
 
479
                prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)));
 
480
 
 
481
        if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) {
 
482
                prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
 
483
                prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
 
484
        }
 
485
 
 
486
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) {
 
487
                r = NULL;
 
488
                goto err_allocs;
 
489
        }
 
490
 
 
491
        if (!(r = drmMalloc(sizeof(*r))))
 
492
                return NULL;
 
493
 
 
494
        r->prop_id = prop.prop_id;
 
495
        r->count_values = prop.count_values;
 
496
 
 
497
        r->flags = prop.flags;
 
498
        if (prop.count_values)
 
499
                r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t));
 
500
        if (prop.flags & DRM_MODE_PROP_ENUM) {
 
501
                r->count_enums = prop.count_enum_blobs;
 
502
                r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum));
 
503
        } else if (prop.flags & DRM_MODE_PROP_BLOB) {
 
504
                r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t));
 
505
                r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t));
 
506
                r->count_blobs = prop.count_enum_blobs;
 
507
        }
 
508
        strncpy(r->name, prop.name, DRM_PROP_NAME_LEN);
 
509
        r->name[DRM_PROP_NAME_LEN-1] = 0;
 
510
 
 
511
err_allocs:
 
512
        drmFree(U642VOID(prop.values_ptr));
 
513
        drmFree(U642VOID(prop.enum_blob_ptr));
 
514
 
 
515
        return r;
 
516
}
 
517
 
 
518
void drmModeFreeProperty(drmModePropertyPtr ptr)
 
519
{
 
520
        if (!ptr)
 
521
                return;
 
522
 
 
523
        drmFree(ptr->values);
 
524
        drmFree(ptr->enums);
 
525
        drmFree(ptr);
 
526
}
 
527
 
 
528
drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id)
 
529
{
 
530
        struct drm_mode_get_blob blob;
 
531
        drmModePropertyBlobPtr r;
 
532
 
 
533
        blob.length = 0;
 
534
        blob.data = 0;
 
535
        blob.blob_id = blob_id;
 
536
 
 
537
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
 
538
                return NULL;
 
539
 
 
540
        if (blob.length)
 
541
                blob.data = VOID2U64(drmMalloc(blob.length));
 
542
 
 
543
        if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
 
544
                r = NULL;
 
545
                goto err_allocs;
 
546
        }
 
547
 
 
548
        if (!(r = drmMalloc(sizeof(*r))))
 
549
                return NULL;
 
550
 
 
551
        r->id = blob.blob_id;
 
552
        r->length = blob.length;
 
553
        r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length);
 
554
 
 
555
err_allocs:
 
556
        drmFree(U642VOID(blob.data));
 
557
        return r;
 
558
}
 
559
 
 
560
void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
 
561
{
 
562
        if (!ptr)
 
563
                return;
 
564
 
 
565
        drmFree(ptr->data);
 
566
        drmFree(ptr);
 
567
}
 
568
 
 
569
int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
 
570
                             uint64_t value)
 
571
{
 
572
        struct drm_mode_connector_set_property osp;
 
573
        int ret;
 
574
 
 
575
        osp.connector_id = connector_id;
 
576
        osp.prop_id = property_id;
 
577
        osp.value = value;
 
578
 
 
579
        if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)))
 
580
                return ret;
 
581
 
 
582
        return 0;
 
583
}
 
584
 
 
585
/*
 
586
 * checks if a modesetting capable driver has attached to the pci id
 
587
 * returns 0 if modesetting supported.
 
588
 *  -EINVAL or invalid bus id
 
589
 *  -ENOSYS if no modesetting support
 
590
*/
 
591
int drmCheckModesettingSupported(const char *busid)
 
592
{
 
593
#ifdef __linux__
 
594
        char pci_dev_dir[1024];
 
595
        int domain, bus, dev, func;
 
596
        DIR *sysdir;
 
597
        struct dirent *dent;
 
598
        int found = 0, ret;
 
599
 
 
600
        ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func);
 
601
        if (ret != 4)
 
602
                return -EINVAL;
 
603
 
 
604
        sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm",
 
605
                domain, bus, dev, func);
 
606
 
 
607
        sysdir = opendir(pci_dev_dir);
 
608
        if (sysdir) {
 
609
                dent = readdir(sysdir);
 
610
                while (dent) {
 
611
                        if (!strncmp(dent->d_name, "controlD", 8)) {
 
612
                                found = 1;
 
613
                                break;
 
614
                        }
 
615
 
 
616
                        dent = readdir(sysdir);
 
617
                }
 
618
                closedir(sysdir);
 
619
                if (found)
 
620
                        return 0;
 
621
        }
 
622
 
 
623
        sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
 
624
                domain, bus, dev, func);
 
625
 
 
626
        sysdir = opendir(pci_dev_dir);
 
627
        if (!sysdir)
 
628
                return -EINVAL;
 
629
 
 
630
        dent = readdir(sysdir);
 
631
        while (dent) {
 
632
                if (!strncmp(dent->d_name, "drm:controlD", 12)) {
 
633
                        found = 1;
 
634
                        break;
 
635
                }
 
636
 
 
637
                dent = readdir(sysdir);
 
638
        }
 
639
 
 
640
        closedir(sysdir);
 
641
        if (found)
 
642
                return 0;
 
643
#endif
 
644
        return -ENOSYS;
 
645
 
 
646
}
 
647
 
 
648
int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
 
649
                        uint16_t *red, uint16_t *green, uint16_t *blue)
 
650
{
 
651
        int ret;
 
652
        struct drm_mode_crtc_lut l;
 
653
 
 
654
        l.crtc_id = crtc_id;
 
655
        l.gamma_size = size;
 
656
        l.red = VOID2U64(red);
 
657
        l.green = VOID2U64(green);
 
658
        l.blue = VOID2U64(blue);
 
659
 
 
660
        if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_GETGAMMA, &l)))
 
661
                return ret;
 
662
 
 
663
        return 0;
 
664
}
 
665
 
 
666
int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
 
667
                        uint16_t *red, uint16_t *green, uint16_t *blue)
 
668
{
 
669
        int ret;
 
670
        struct drm_mode_crtc_lut l;
 
671
 
 
672
        l.crtc_id = crtc_id;
 
673
        l.gamma_size = size;
 
674
        l.red = VOID2U64(red);
 
675
        l.green = VOID2U64(green);
 
676
        l.blue = VOID2U64(blue);
 
677
 
 
678
        if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETGAMMA, &l)))
 
679
                return ret;
 
680
 
 
681
        return 0;
 
682
}
 
683
 
 
684
int drmHandleEvent(int fd, drmEventContextPtr evctx)
 
685
{
 
686
        char buffer[1024];
 
687
        int len, i;
 
688
        struct drm_event *e;
 
689
        struct drm_event_vblank *vblank;
 
690
        
 
691
        /* The DRM read semantics guarantees that we always get only
 
692
         * complete events. */
 
693
 
 
694
        len = read(fd, buffer, sizeof buffer);
 
695
        if (len == 0)
 
696
                return 0;
 
697
        if (len < sizeof *e)
 
698
                return -1;
 
699
 
 
700
        i = 0;
 
701
        while (i < len) {
 
702
                e = (struct drm_event *) &buffer[i];
 
703
                switch (e->type) {
 
704
                case DRM_EVENT_VBLANK:
 
705
                        if (evctx->version < 1 ||
 
706
                            evctx->vblank_handler == NULL)
 
707
                                break;
 
708
                        vblank = (struct drm_event_vblank *) e;
 
709
                        evctx->vblank_handler(fd,
 
710
                                              vblank->sequence, 
 
711
                                              vblank->tv_sec,
 
712
                                              vblank->tv_usec,
 
713
                                              U642VOID (vblank->user_data));
 
714
                        break;
 
715
                case DRM_EVENT_FLIP_COMPLETE:
 
716
                        if (evctx->version < 2 ||
 
717
                            evctx->page_flip_handler == NULL)
 
718
                                break;
 
719
                        vblank = (struct drm_event_vblank *) e;
 
720
                        evctx->page_flip_handler(fd,
 
721
                                                 vblank->sequence,
 
722
                                                 vblank->tv_sec,
 
723
                                                 vblank->tv_usec,
 
724
                                                 U642VOID (vblank->user_data));
 
725
                        break;
 
726
                default:
 
727
                        break;
 
728
                }
 
729
                i += e->length;
 
730
        }
 
731
 
 
732
        return 0;
 
733
}
 
734
 
 
735
int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id,
 
736
                    uint32_t flags, void *user_data)
 
737
{
 
738
        struct drm_mode_crtc_page_flip flip;
 
739
 
 
740
        flip.fb_id = fb_id;
 
741
        flip.crtc_id = crtc_id;
 
742
        flip.user_data = VOID2U64(user_data);
 
743
        flip.flags = flags;
 
744
        flip.reserved = 0;
 
745
 
 
746
        return drmIoctl(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip);
 
747
}