From: Roman Moravcik Date: Thu, 7 Jan 2010 11:31:19 +0000 (+0100) Subject: Added initialization of camera. This should prevent breaking of camera X-Git-Tag: v0.3~4 X-Git-Url: http://git.maemo.org/git/?p=flashlight-appl;a=commitdiff_plain;h=4dda7ac8ce557272797639d7e6e95089dc4629e9 Added initialization of camera. This should prevent breaking of camera application (bug 4949). --- diff --git a/src/flashlight_lib.c b/src/flashlight_lib.c index 6f56ede..d7ce455 100644 --- a/src/flashlight_lib.c +++ b/src/flashlight_lib.c @@ -26,12 +26,21 @@ #include #include #include +#include #include #include #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; @@ -104,6 +113,8 @@ int flashlight_get_status (FlashlightContext_t *flashlight, int *status) 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); @@ -128,6 +139,35 @@ int flashlight_set_intensity (FlashlightContext_t *flashlight, int 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; } @@ -161,6 +201,10 @@ int flashlight_get_intensity (FlashlightContext_t *flashlight, int *intensity) 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); @@ -205,11 +249,92 @@ int flashlight_open (FlashlightContext_t *flashlight, const char *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) { @@ -217,6 +342,15 @@ int flashlight_close (FlashlightContext_t *flashlight) 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));