#include <errno.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
+#include <sys/mman.h>
#include <asm/types.h>
#include <linux/videodev2.h>
#include "flashlight_lib.h"
+struct buffer {
+ void *start;
+ size_t length;
+};
+
+struct buffer *buffers = NULL;
+static unsigned int n_buffers = 0;
+
int flashlight_get_status (FlashlightContext_t *flashlight, int *status)
{
struct v4l2_control ctrl;
int flashlight_set_intensity (FlashlightContext_t *flashlight, int intensity)
{
struct v4l2_control ctrl;
+ enum v4l2_buf_type type;
+ unsigned int i;
printf ("flashlight_set_intensity(%d)\n", intensity);
return EGENERROR;
}
+ /*
+ WORKAROUND: start/stop i/o streaming to block camera application
+ */
+ if (intensity > 0) {
+ for (i = 0; i < n_buffers; ++i) {
+ struct v4l2_buffer buf;
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = i;
+ if (ioctl (flashlight->fd, VIDIOC_QBUF, &buf) == -1) {
+ printf ("flashlight_set_intensity: unable to exchange a buffer %d with driver (%s)\n", i, strerror (errno));
+ return EGENERROR;
+ }
+ }
+
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (ioctl (flashlight->fd, VIDIOC_STREAMON, &type)) {
+ printf ("flashlight_set_intensity: unable to start i/o streaming (%s)\n", strerror (errno));
+ return EGENERROR;
+ }
+ } else {
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (ioctl (flashlight->fd, VIDIOC_STREAMOFF, &type) == -1) {
+ printf ("flashlight_set_intensity: unable to stop i/o streaming (%s)\n", strerror (errno));
+ return EGENERROR;
+ }
+ }
+
return ENOERROR;
}
int flashlight_open (FlashlightContext_t *flashlight, const char *device_name)
{
struct v4l2_queryctrl ctrl;
+ struct v4l2_cropcap cropcap;
+ struct v4l2_crop crop;
+ struct v4l2_format fmt;
+ struct v4l2_requestbuffers req;
struct stat st;
printf ("flashlight_open(%s)\n", device_name);
flashlight->min_intensity = ctrl.minimum;
flashlight->max_intensity = ctrl.maximum;
+ /*
+ WORKAROUND: Initialization of camera extracted from v4l2_example.
+ http://v4l2spec.bytesex.org/spec/capture-example.html
+
+ We need to initialize camera in other to block camera application.
+ (bug 4949: Applet breaks the camera application)
+ */
+ /* get crop capabilities */
+ cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (ioctl (flashlight->fd, VIDIOC_CROPCAP, &cropcap) == -1) {
+ printf ("flashlight_open: unable to get crop capabilities (%s)\n", strerror (errno));
+ return EGENERROR;
+ }
+
+ /* set crop capabilities */
+ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ crop.c = cropcap.defrect; /* reset to default */
+ if (ioctl (flashlight->fd, VIDIOC_S_CROP, &crop) == -1) {
+ printf ("flashlight_open: unable to set cropping rectangle (%s)\n", strerror (errno));
+ return EGENERROR;
+ }
+
+ /* set data format */
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.width = 640;
+ fmt.fmt.pix.height = 480;
+ fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+ if (ioctl (flashlight->fd, VIDIOC_S_FMT, &fmt) == -1) {
+ printf ("flashlight_open: unable to set data format (%s)\n", strerror (errno));
+ return EGENERROR;
+ }
+
+ req.count = 4;
+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ req.memory = V4L2_MEMORY_MMAP;
+ if (ioctl (flashlight->fd, VIDIOC_REQBUFS, &req) == -1) {
+ printf ("flashlight_open: unable to initiate memory mapping (%s)\n", strerror (errno));
+ return EGENERROR;
+ }
+
+ if (req.count < 2) {
+ printf ("flashlight_open: insufficient buffer memory on %s\n", device_name);
+ return EGENERROR;
+ }
+
+ buffers = calloc (req.count, sizeof (*buffers));
+ if (!buffers) {
+ printf ("flashlight_open: unable to allocate memory\n");
+ return EGENERROR;
+ }
+
+ for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
+ struct v4l2_buffer buf;
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = n_buffers;
+
+ if (ioctl (flashlight->fd, VIDIOC_QUERYBUF, &buf) == -1) {
+ printf ("flashlight_open: unable to query the status of a buffer %d (%s)\n",
+ n_buffers, strerror (errno));
+ return EGENERROR;
+ }
+
+ buffers[n_buffers].length = buf.length;
+ buffers[n_buffers].start = mmap (NULL /* start anywhere */,
+ buf.length,
+ PROT_READ | PROT_WRITE /* required */,
+ MAP_SHARED /* recommended */,
+ flashlight->fd,
+ buf.m.offset);
+
+ if (buffers[n_buffers].start == MAP_FAILED) {
+ printf ("flashlight_open: unable to map memory (%s)\n", strerror (errno));
+ return EGENERROR;
+ }
+ }
+
return ENOERROR;
}
int flashlight_close (FlashlightContext_t *flashlight)
{
+ unsigned int i;
+
printf ("flashlight_close()\n");
if (flashlight == NULL) {
return ENOCONTEXT;
}
+ /* unmap memory mapped buffers */
+ for (i = 0; i < n_buffers; ++i) {
+ if (munmap (buffers[i].start, buffers[i].length) == -1) {
+ printf ("flashlight_close: unable to unmap memory (%s)\n", strerror (errno));
+ return EGENERROR;
+ }
+ }
+ free (buffers);
+
if (flashlight->fd != -1) {
if (close (flashlight->fd) == -1) {
printf ("flashlight_close: cannot close device '%s' (%s)\n", flashlight->device_name, strerror (errno));