package base

const (
	_IOC_NRBITS   = 8
	_IOC_TYPEBITS = 8
	_IOC_SIZEBITS = 14
	_IOC_DIRBITS  = 2
	_IOC_NRSHIFT  = 0
)

const (
	_IOC_NRMASK   = ((1 << _IOC_NRBITS) - 1)
	_IOC_TYPEMASK = ((1 << _IOC_TYPEBITS) - 1)
	_IOC_SIZEMASK = ((1 << _IOC_SIZEBITS) - 1)
	_IOC_DIRMASK  = ((1 << _IOC_DIRBITS) - 1)
)

const (
	_IOC_TYPESHIFT = (_IOC_NRSHIFT + _IOC_NRBITS)
	_IOC_SIZESHIFT = (_IOC_TYPESHIFT + _IOC_TYPEBITS)
	_IOC_DIRSHIFT  = (_IOC_SIZESHIFT + _IOC_SIZEBITS)
)

const (
	_IOC_NONE = iota
	_IOC_WRITE
	_IOC_READ
)
const (
	IOC_IN        = (_IOC_WRITE << _IOC_DIRSHIFT)
	IOC_OUT       = (_IOC_READ << _IOC_DIRSHIFT)
	IOC_INOUT     = ((_IOC_WRITE | _IOC_READ) << _IOC_DIRSHIFT)
	IOCSIZE_MASK  = (_IOC_SIZEMASK << _IOC_SIZESHIFT)
	IOCSIZE_SHIFT = (_IOC_SIZESHIFT)
)

func IOC(dir uint32, tp uint32, nr uint32, size uint32) uint32 {
	return (((dir) << _IOC_DIRSHIFT) | ((tp) << _IOC_TYPESHIFT) | ((nr) << _IOC_NRSHIFT) | ((size) << _IOC_SIZESHIFT))
}

func IO(tp uint32, nr uint32) uint32 {
	return IOC(_IOC_NONE, tp, nr, 0)
}

func IOR(tp uint32, nr uint32, size uint32) uint32 {
	return IOC(_IOC_READ, tp, nr, size)
}

func IOW(tp uint32, nr uint32, size uint32) uint32 {
	return IOC(_IOC_WRITE, tp, nr, size)
}

func IOWR(tp uint32, nr uint32, size uint32) uint32 {
	return IOC(_IOC_READ|_IOC_READ, tp, nr, size)
}

func IOR_BAD(tp uint32, nr uint32, size uint32) uint32 {
	return IOC(_IOC_READ, (tp), (nr), size)
}

func IOW_BAD(tp uint32, nr uint32, size uint32) uint32 {
	return IOC(_IOC_WRITE, (tp), (nr), size)
}

func IOWR_BAD(tp uint32, nr uint32, size uint32) uint32 {
	return IOC(_IOC_READ|_IOC_WRITE, (tp), (nr), size)
}

func IOC_DIR(nr uint32) uint32 {
	return (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
}

func IOC_TYPE(nr uint32) uint32 {
	return (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
}

func IOC_NR(nr uint32) uint32   { return (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) }
func IOC_SIZE(nr uint32) uint32 { return (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) }
