libdrm 0.0.2

A reimplementation of the libdrm middleware library
Documentation
#![feature(concat_idents)]
#![feature(type_ascription)]
#![feature(conservative_impl_trait)]

extern crate drm_sys;
extern crate libc;
extern crate smallvec;
#[macro_use]
extern crate error_chain;

#[macro_use]
mod util;
use util::*;

use control::Control;
use control::MasterControl;

pub mod result;
pub mod control;

use std::os::unix::io::{RawFd, AsRawFd};
use std::ptr::null_mut;
use libc::{ioctl, c_void, c_char};
use drm_sys::*;
use self::result::Result;

#[derive(Debug)]
pub struct DriverInfo {
    ver: (i32, i32, i32),
    name: Array<c_char>,
    date: Array<c_char>,
    desc: Array<c_char>
}

#[derive(Debug)]
/// A token unique to the process that determines who opened the device.
///
/// This token can be sent to another process that acts as the DRM Master and
/// then authenticated to give extra privileges.
pub struct AuthToken(u32);

#[derive(Debug)]
/// Capabilities that the process understands.
///
/// These can be used to tell the DRM device what capabilities the process can
/// use.
pub enum ClientCapability {
    Stereo3D = DRM_CLIENT_CAP_STEREO_3D as isize,
    UniversalPlanes = DRM_CLIENT_CAP_UNIVERSAL_PLANES as isize,
    Atomic = DRM_CLIENT_CAP_ATOMIC as isize
}

/// A trait for all DRM devices.
pub trait Device : AsRawFd + Sized {
    /// Generates and returns a magic token unique to the current process. This
    /// token can be used to authenticate with the DRM Master.
    fn magic(&self) -> Result<AuthToken> {
        let raw: drm_auth_t = Default::default();
        ioctl!(self, MACRO_DRM_IOCTL_GET_MAGIC, &raw);
        Ok(AuthToken(raw.magic))
    }

    // Returns stat information about the device.
    // TODO Finish this when we get data from stats.
    fn stats(&self) -> Result<()> {
        unimplemented!()
    }

    /// Tells the DRM device whether we understand or do not understand a
    /// particular capability. Some features, such as atomic modesetting,
    /// require informing the device that the process can use such features
    /// before it will expose them.
    fn set_client_cap(&self, cap: ClientCapability, set: bool) -> Result<()> {
        let mut raw: drm_set_client_cap = Default::default();
        raw.capability = cap as u64;
        raw.value = set as u64;
        ioctl!(self, MACRO_DRM_IOCTL_SET_CLIENT_CAP, &raw);
        Ok(())
    }

    // Waits for the next VBlank to appear.
    // TODO Implement with EINTR
    fn wait_vblan(&self) -> () {
        unimplemented!()
    }
}

/// A trait for DRM devices that do not hold the master lock.
pub trait UnprivilegedDevice : Device {
    fn set_master<'a>(&'a self) -> Result<MasterRef<'a, Self>> {
        ioctl!(self, MACRO_DRM_IOCTL_SET_MASTER, null_mut() as *mut c_void);
        Ok(MasterRef(self))
    }
}

/// A trait for DRM devices that may be holding the master lock.
pub trait MasterDevice : Device {
    fn drop_master(&self) -> Result<()> {
        ioctl!(self, MACRO_DRM_IOCTL_DROP_MASTER, null_mut() as *mut c_void);
        Ok(())
    }
}

#[derive(Debug)]
/// A simple handle to the DRM Master lock. This can be generated by any object
/// that implements the UnprivilegedDevice trait.
pub struct MasterRef<'a, T>(&'a T) where T: 'a + Device;

impl<'a, T> AsRawFd for MasterRef<'a, T> where T: 'a + Device {
    fn as_raw_fd(&self) -> RawFd {
        self.0.as_raw_fd()
    }
}

impl<'a, T> Device for MasterRef<'a, T> where T: 'a + Device {}
impl<'a, T> MasterDevice for MasterRef<'a, T> where T: 'a + Device {}
impl<'a, T> Control for MasterRef<'a, T> where T: 'a + Device {}
impl<'a, T> MasterControl for MasterRef<'a, T> where T: 'a + Device {}