Skip to content

Instantly share code, notes, and snippets.

@stanier
Created March 14, 2017 04:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stanier/c71c0b2f7d29d52399b660eb1d0f869a to your computer and use it in GitHub Desktop.
Save stanier/c71c0b2f7d29d52399b660eb1d0f869a to your computer and use it in GitHub Desktop.
IOCTL problem
package ioctl
import "golang.org/x/sys/unix"
const (
typeBits = 8
numberBits = 8
sizeBits = 14
directionBits = 2
typeMask = (1 << typeBits) - 1
numberMask = (1 << numberBits) - 1
sizeMask = (1 << sizeBits) - 1
directionMask = (1 << directionBits) - 1
directionNone = 0
directionWrite = 1
directionRead = 2
numberShift = 0
typeShift = numberShift + numberBits
sizeShift = typeShift + typeBits
directionShift = sizeShift + sizeBits
)
func ioc(dir, t, nr, size uintptr) uintptr {
return (dir << directionShift) | (t << typeShift) | (nr << numberShift) | (size << sizeShift)
}
// Io used for a simple ioctl that sends nothing but the type and number, and receives back nothing but an (integer) retval.
func Io(t, nr uintptr) uintptr {
return ioc(directionNone, t, nr, 0)
}
// IoR used for an ioctl that reads data from the device driver. The driver will be allowed to return sizeof(data_type) bytes to the user.
func IoR(t, nr, size uintptr) uintptr {
return ioc(directionRead, t, nr, size)
}
// IoW used for an ioctl that writes data to the device driver.
func IoW(t, nr, size uintptr) uintptr {
return ioc(directionWrite, t, nr, size)
}
// IoRW a combination of IoR and IoW. That is, data is both written to the driver and then read back from the driver by the client.
func IoRW(t, nr, size uintptr) uintptr {
return ioc(directionRead|directionWrite, t, nr, size)
}
// Ioctl simplified ioct call
func Ioctl(fd, op, arg uintptr) error {
_, _, ep := unix.Syscall(unix.SYS_IOCTL, fd, op, arg)
if ep != 0 {
return ep
}
return nil
}
package main
import (
"unsafe"
"./ioctl"
)
const (
V4L2_CTRL_CLASS_USER uint32 = 0x980000
V4L2_CID_BASE uint32 = (V4L2_CTRL_CLASS_USER | 0x900)
V4L2_CTRL_CLASS_CAMERA uint32 = 0x9a0000
V4L2_CID_CAMERA_CLASS_BASE uint32 = (V4L2_CTRL_CLASS_CAMERA | 0x900)
V4L2_CID_CAMERA_CLASS uint32 = (V4L2_CTRL_CLASS_CAMERA | 1)
)
const (
V4L2_CID_EXPOSURE uint32 = V4L2_CID_BASE + 17
V4L2_CID_EXPOSURE_AUTO uint32 = V4L2_CID_CAMERA_CLASS_BASE + 1
V4L2_CID_EXPOSURE_ABSOLUTE uint32 = V4L2_CID_CAMERA_CLASS_BASE + 2
V4L2_CID_EXPOSURE_AUTO_PRIORITY uint32 = V4L2_CID_CAMERA_CLASS_BASE + 3
)
const (
V4L2_EXPOSURE_AUTO int32 = iota
V4L2_EXPOSURE_MANUAL int32 = iota
V4L2_EXPOSURE_SHUTTER_PRIORITY int32 = iota
V4L2_EXPOSURE_APERTURE_PRIORITY int32 = iota
)
var (
VIDIOC_S_EXT_CTRLS = ioctl.IoRW(uintptr('V'), 72, unsafe.Sizeof(v4l2_ext_controls{}))
VIDIOC_S_CTRL = ioctl.IoRW(uintptr('V'), 28, unsafe.Sizeof(v4l2_control{}))
)
func setExposureA(fd uintptr, exposure_value *int32) error {
exposure := &v4l2_control{
id: V4L2_CID_EXPOSURE,
value: *exposure_value,
}
err := ioctl.Ioctl(fd, VIDIOC_S_CTRL, uintptr(unsafe.Pointer(exposure)))
controls := &v4l2_ext_controls{
ctrl_class: V4L2_CTRL_CLASS_CAMERA,
count: uint32(1),
//error_idx: 0,
reserved: [2]uint32{uint32(0), uint32(0)},
controls: &[1]v4l2_ext_control{
v4l2_ext_control{
id: V4L2_CID_EXPOSURE_AUTO,
size: uint32(unsafe.Sizeof(uintptr(*exposure_value))),
reserved2: [1]uint32{0},
value: *exposure_value,
},
},
}
err := ioctl.Ioctl(fd, VIDIOC_S_EXT_CTRLS, uintptr(unsafe.Pointer(controls)))
if err != nil {
return err
}
return nil
}
func setExposureB(fd uintptr, exposure_value *int32) error {
control := &v4l2_control{
id: V4L2_CID_EXPOSURE,
value: *exposure_value,
}
err := ioctl.Ioctl(fd, VIDIOC_S_CTRL, uintptr(unsafe.Pointer(control)))
if err != nil {
return err
}
return nil
}
func main() {
if err = cam.SetExposure(0); err != nil {
panic(err.Error())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment