Home | History | Annotate | Download | only in xcore
      1 /*
      2  * v4l2_device.cpp - v4l2 device
      3  *
      4  *  Copyright (c) 2014-2015 Intel Corporation
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  *
     18  * Author: Wind Yuan <feng.yuan (at) intel.com>
     19  * Author: John Ye <john.ye (at) intel.com>
     20  */
     21 
     22 #include "v4l2_device.h"
     23 #include <sys/ioctl.h>
     24 #include <stdlib.h>
     25 #include <unistd.h>
     26 #include <fcntl.h>
     27 #include <poll.h>
     28 #include <errno.h>
     29 #include <sys/mman.h>
     30 
     31 #include "v4l2_buffer_proxy.h"
     32 
     33 namespace XCam {
     34 
     35 #define XCAM_V4L2_DEFAULT_BUFFER_COUNT  6
     36 
     37 V4l2Device::V4l2Device (const char *name)
     38     : _name (NULL)
     39     , _fd (-1)
     40     , _sensor_id (0)
     41     , _capture_mode (0)
     42     , _capture_buf_type (V4L2_BUF_TYPE_VIDEO_CAPTURE)
     43     , _memory_type (V4L2_MEMORY_MMAP)
     44     , _fps_n (0)
     45     , _fps_d (0)
     46     , _active (false)
     47     , _buf_count (XCAM_V4L2_DEFAULT_BUFFER_COUNT)
     48 {
     49     if (name)
     50         _name = strndup (name, XCAM_MAX_STR_SIZE);
     51     xcam_mem_clear (_format);
     52 }
     53 
     54 V4l2Device::~V4l2Device ()
     55 {
     56     close();
     57     if (_name)
     58         xcam_free (_name);
     59 }
     60 
     61 bool
     62 V4l2Device::set_device_name (const char *name)
     63 {
     64     XCAM_ASSERT (name);
     65 
     66     if (is_opened()) {
     67         XCAM_LOG_WARNING ("can't set device name since device opened");
     68         return false;
     69     }
     70     if (_name)
     71         xcam_free (_name);
     72     _name = strndup (name, XCAM_MAX_STR_SIZE);
     73     return true;
     74 }
     75 
     76 bool
     77 V4l2Device::set_sensor_id (int id)
     78 {
     79     if (is_opened()) {
     80         XCAM_LOG_WARNING ("can't set sensor id since device opened");
     81         return false;
     82     }
     83     _sensor_id = id;
     84     return true;
     85 }
     86 
     87 bool
     88 V4l2Device::set_capture_mode (uint32_t capture_mode)
     89 {
     90     if (is_opened()) {
     91         XCAM_LOG_WARNING ("can't set sensor id since device opened");
     92         return false;
     93     }
     94     _capture_mode = capture_mode;
     95     return true;
     96 }
     97 
     98 bool
     99 V4l2Device::set_framerate (uint32_t n, uint32_t d)
    100 {
    101     if (_format.fmt.pix.pixelformat) {
    102         XCAM_LOG_WARNING ("device(%s) set framerate failed since formatted was already set.", XCAM_STR(_name));
    103         return false;
    104     }
    105 
    106     _fps_n = n;
    107     _fps_d = d;
    108 
    109     return true;
    110 }
    111 
    112 void
    113 V4l2Device::get_framerate (uint32_t &n, uint32_t &d)
    114 {
    115     n = _fps_n;
    116     d = _fps_d;
    117 }
    118 
    119 bool
    120 V4l2Device::set_mem_type (enum v4l2_memory type) {
    121     if (is_activated ()) {
    122         XCAM_LOG_WARNING ("device(%s) set mem type failed", XCAM_STR (_name));
    123         return false;
    124     }
    125     _memory_type = type;
    126     return true;
    127 }
    128 
    129 bool
    130 V4l2Device::set_buffer_count (uint32_t buf_count)
    131 {
    132     if (is_activated ()) {
    133         XCAM_LOG_WARNING ("device(%s) set buffer count failed", XCAM_STR (_name));
    134         return false;
    135     }
    136     _buf_count = buf_count;
    137     return true;
    138 }
    139 
    140 
    141 XCamReturn
    142 V4l2Device::open ()
    143 {
    144     struct v4l2_streamparm param;
    145 
    146     if (is_opened()) {
    147         XCAM_LOG_DEBUG ("device(%s) was already opened", XCAM_STR(_name));
    148         return XCAM_RETURN_NO_ERROR;
    149     }
    150 
    151     if (!_name) {
    152         XCAM_LOG_DEBUG ("v4l2 device open failed, there's no device name");
    153         return XCAM_RETURN_ERROR_PARAM;
    154     }
    155     _fd = ::open (_name, O_RDWR);
    156     if (_fd == -1) {
    157         XCAM_LOG_DEBUG ("open device(%s) failed", _name);
    158         return XCAM_RETURN_ERROR_IOCTL;
    159     }
    160 
    161     // set sensor id
    162     if (io_control (VIDIOC_S_INPUT, &_sensor_id) < 0) {
    163         XCAM_LOG_WARNING ("set sensor id(%d) failed but continue", _sensor_id);
    164     }
    165 
    166     // set capture mode
    167     xcam_mem_clear (param);
    168     param.type = _capture_buf_type;
    169     param.parm.capture.capturemode = _capture_mode;
    170     if (io_control (VIDIOC_S_PARM, &param) < 0) {
    171         XCAM_LOG_WARNING ("set capture mode(0x%08x) failed but continue", _capture_mode);
    172     }
    173 
    174     return XCAM_RETURN_NO_ERROR;
    175 }
    176 
    177 XCamReturn
    178 V4l2Device::close ()
    179 {
    180     if (!is_opened())
    181         return XCAM_RETURN_NO_ERROR;
    182     ::close (_fd);
    183     _fd = -1;
    184     return XCAM_RETURN_NO_ERROR;
    185 }
    186 
    187 int
    188 V4l2Device::io_control (int cmd, void *arg)
    189 
    190 {
    191     if (_fd <= 0)
    192         return -1;
    193 
    194     return xcam_device_ioctl (_fd, cmd, arg);
    195 }
    196 
    197 int
    198 V4l2Device::poll_event (int timeout_msec)
    199 {
    200     struct pollfd poll_fd;
    201     int ret = 0;
    202 
    203     XCAM_ASSERT (_fd > 0);
    204 
    205     xcam_mem_clear (poll_fd);
    206     poll_fd.fd = _fd;
    207     poll_fd.events = (POLLPRI | POLLIN | POLLERR | POLLNVAL | POLLHUP);
    208 
    209     ret = poll (&poll_fd, 1, timeout_msec);
    210     if (ret > 0 && (poll_fd.revents & (POLLERR | POLLNVAL | POLLHUP))) {
    211         XCAM_LOG_DEBUG ("v4l2 subdev(%s) polled error", XCAM_STR(_name));
    212         return -1;
    213     }
    214     return ret;
    215 
    216 }
    217 
    218 XCamReturn
    219 V4l2Device::set_format (struct v4l2_format &format)
    220 {
    221     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    222 
    223     XCAM_FAIL_RETURN (ERROR, !is_activated (), XCAM_RETURN_ERROR_PARAM,
    224                       "Cannot set format to v4l2 device while it is active.");
    225 
    226     XCAM_FAIL_RETURN (ERROR, is_opened (), XCAM_RETURN_ERROR_FILE,
    227                       "Cannot set format to v4l2 device while it is closed.");
    228 
    229     struct v4l2_format tmp_format = format;
    230 
    231     ret = pre_set_format (format);
    232     if (ret != XCAM_RETURN_NO_ERROR) {
    233         XCAM_LOG_WARNING ("device(%s) pre_set_format failed", XCAM_STR (_name));
    234         return ret;
    235     }
    236 
    237     if (io_control (VIDIOC_S_FMT, &format) < 0) {
    238         if (errno == EBUSY) {
    239             // TODO log device name
    240             XCAM_LOG_ERROR("Video device is busy, fail to set format.");
    241         } else {
    242             // TODO log format details and errno
    243             XCAM_LOG_ERROR("Fail to set format: %s", strerror(errno));
    244         }
    245 
    246         return XCAM_RETURN_ERROR_IOCTL;
    247     }
    248 
    249     if (tmp_format.fmt.pix.width != format.fmt.pix.width || tmp_format.fmt.pix.height != format.fmt.pix.height) {
    250         XCAM_LOG_ERROR (
    251             "device(%s) set v4l2 format failed, supported format: width:%d, height:%d",
    252             XCAM_STR (_name),
    253             format.fmt.pix.width,
    254             format.fmt.pix.height);
    255 
    256         return XCAM_RETURN_ERROR_PARAM;
    257     }
    258 
    259     while (_fps_n && _fps_d) {
    260         struct v4l2_streamparm param;
    261         xcam_mem_clear (param);
    262         param.type = _capture_buf_type;
    263         if (io_control (VIDIOC_G_PARM, &param) < 0) {
    264             XCAM_LOG_WARNING ("device(%s) set framerate failed on VIDIOC_G_PARM but continue", XCAM_STR (_name));
    265             break;
    266         }
    267 
    268         if (!(param.parm.capture.capability & V4L2_CAP_TIMEPERFRAME))
    269             break;
    270 
    271         param.parm.capture.timeperframe.numerator = _fps_d;
    272         param.parm.capture.timeperframe.denominator = _fps_n;
    273 
    274         if (io_control (VIDIOC_S_PARM, &param) < 0) {
    275             XCAM_LOG_WARNING ("device(%s) set framerate failed on VIDIOC_S_PARM but continue", XCAM_STR (_name));
    276             break;
    277         }
    278         _fps_n = param.parm.capture.timeperframe.denominator;
    279         _fps_d = param.parm.capture.timeperframe.numerator;
    280         XCAM_LOG_INFO ("device(%s) set framerate(%d/%d)", XCAM_STR (_name), _fps_n, _fps_d);
    281 
    282         // exit here, otherwise it is an infinite loop
    283         break;
    284     }
    285 
    286     ret = post_set_format (format);
    287     if (ret != XCAM_RETURN_NO_ERROR) {
    288         XCAM_LOG_WARNING ("device(%s) post_set_format failed", XCAM_STR (_name));
    289         return ret;
    290     }
    291 
    292     _format = format;
    293     XCAM_LOG_INFO (
    294         "device(%s) set format(w:%d, h:%d, pixelformat:%s, bytesperline:%d,image_size:%d)",
    295         XCAM_STR (_name),
    296         format.fmt.pix.width, format.fmt.pix.height,
    297         xcam_fourcc_to_string (format.fmt.pix.pixelformat),
    298         format.fmt.pix.bytesperline,
    299         format.fmt.pix.sizeimage);
    300 
    301     return XCAM_RETURN_NO_ERROR;
    302 }
    303 
    304 /*! \brief v4l2 set format
    305  *
    306  * \param[in]    width            format width
    307  * \param[in]    height           format height
    308  * \param[in]    pixelformat      fourcc
    309  * \param[in]    field            V4L2_FIELD_INTERLACED or V4L2_FIELD_NONE
    310  */
    311 XCamReturn
    312 V4l2Device::set_format (
    313     uint32_t width,  uint32_t height,
    314     uint32_t pixelformat, enum v4l2_field field, uint32_t bytes_perline)
    315 {
    316 
    317     struct v4l2_format format;
    318     xcam_mem_clear (format);
    319 
    320     format.type = _capture_buf_type;
    321     format.fmt.pix.width = width;
    322     format.fmt.pix.height = height;
    323     format.fmt.pix.pixelformat = pixelformat;
    324     format.fmt.pix.field = field;
    325 
    326     if (bytes_perline != 0)
    327         format.fmt.pix.bytesperline = bytes_perline;
    328     return set_format (format);
    329 }
    330 
    331 XCamReturn
    332 V4l2Device::pre_set_format (struct v4l2_format &format)
    333 {
    334     XCAM_UNUSED (format);
    335     return XCAM_RETURN_NO_ERROR;
    336 }
    337 
    338 XCamReturn
    339 V4l2Device::post_set_format (struct v4l2_format &format)
    340 {
    341     XCAM_UNUSED (format);
    342     return XCAM_RETURN_NO_ERROR;
    343 }
    344 
    345 std::list<struct v4l2_fmtdesc>
    346 V4l2Device::enum_formats ()
    347 {
    348     std::list<struct v4l2_fmtdesc> formats;
    349     struct v4l2_fmtdesc format;
    350     uint32_t i = 0;
    351 
    352     while (1) {
    353         xcam_mem_clear (format);
    354         format.index = i++;
    355         format.type = _capture_buf_type;
    356         if (this->io_control (VIDIOC_ENUM_FMT, &format) < 0) {
    357             if (errno == EINVAL)
    358                 break;
    359             else { // error
    360                 XCAM_LOG_DEBUG ("enum formats failed");
    361                 return formats;
    362             }
    363         }
    364         formats.push_back (format);
    365     }
    366 
    367     return formats;
    368 }
    369 
    370 XCamReturn
    371 V4l2Device::get_format (struct v4l2_format &format)
    372 {
    373     if (is_activated ()) {
    374         format = _format;
    375         return XCAM_RETURN_NO_ERROR;
    376     }
    377 
    378     if (!is_opened ())
    379         return XCAM_RETURN_ERROR_IOCTL;
    380 
    381     xcam_mem_clear (format);
    382     format.type = _capture_buf_type;
    383 
    384     if (this->io_control (VIDIOC_G_FMT, &format) < 0) {
    385         // FIXME: also log the device name?
    386         XCAM_LOG_ERROR("Fail to get format via ioctl VIDVIO_G_FMT.");
    387         return XCAM_RETURN_ERROR_IOCTL;
    388     }
    389 
    390     return XCAM_RETURN_NO_ERROR;
    391 }
    392 
    393 XCamReturn
    394 V4l2Device::start ()
    395 {
    396     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    397     // request buffer first
    398     ret = request_buffer ();
    399     XCAM_FAIL_RETURN (
    400         ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
    401         "device(%s) start failed", XCAM_STR (_name));
    402 
    403     //alloc buffers
    404     ret = init_buffer_pool ();
    405     XCAM_FAIL_RETURN (
    406         ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
    407         "device(%s) start failed", XCAM_STR (_name));
    408 
    409     //queue all buffers
    410     for (uint32_t i = 0; i < _buf_count; ++i) {
    411         SmartPtr<V4l2Buffer> &buf = _buf_pool [i];
    412         XCAM_ASSERT (buf.ptr());
    413         XCAM_ASSERT (buf->get_buf().index == i);
    414         ret = queue_buffer (buf);
    415         if (ret != XCAM_RETURN_NO_ERROR) {
    416             XCAM_LOG_ERROR (
    417                 "device(%s) start failed on queue index:%d",
    418                 XCAM_STR (_name), i);
    419             stop ();
    420             return ret;
    421         }
    422     }
    423 
    424     // stream on
    425     if (io_control (VIDIOC_STREAMON, &_capture_buf_type) < 0) {
    426         XCAM_LOG_ERROR (
    427             "device(%s) start failed on VIDIOC_STREAMON",
    428             XCAM_STR (_name));
    429         stop ();
    430         return XCAM_RETURN_ERROR_IOCTL;
    431     }
    432     _active = true;
    433     XCAM_LOG_INFO ("device(%s) started successfully", XCAM_STR (_name));
    434     return XCAM_RETURN_NO_ERROR;
    435 }
    436 
    437 XCamReturn
    438 V4l2Device::stop ()
    439 {
    440     // stream off
    441     if (_active) {
    442         if (io_control (VIDIOC_STREAMOFF, &_capture_buf_type) < 0) {
    443             XCAM_LOG_WARNING ("device(%s) steamoff failed", XCAM_STR (_name));
    444         }
    445         _active = false;
    446     }
    447 
    448     fini_buffer_pool ();
    449 
    450     XCAM_LOG_INFO ("device(%s) stopped", XCAM_STR (_name));
    451     return XCAM_RETURN_NO_ERROR;
    452 }
    453 
    454 XCamReturn
    455 V4l2Device::request_buffer ()
    456 {
    457     struct v4l2_requestbuffers request_buf;
    458 
    459     XCAM_ASSERT (!is_activated());
    460 
    461     xcam_mem_clear (request_buf);
    462     request_buf.type = _capture_buf_type;
    463     request_buf.count = _buf_count;
    464     request_buf.memory = _memory_type;
    465 
    466     if (io_control (VIDIOC_REQBUFS, &request_buf) < 0) {
    467         XCAM_LOG_INFO ("device(%s) starts failed on VIDIOC_REQBUFS", XCAM_STR (_name));
    468         return XCAM_RETURN_ERROR_IOCTL;
    469     }
    470 
    471     if (request_buf.count != _buf_count) {
    472         XCAM_LOG_DEBUG (
    473             "device(%s) request buffer count doesn't match user settings, reset buffer count to %d",
    474             XCAM_STR (_name), request_buf.count);
    475         _buf_count = request_buf.count;
    476     }
    477     return XCAM_RETURN_NO_ERROR;
    478 }
    479 
    480 XCamReturn
    481 V4l2Device::allocate_buffer (
    482     SmartPtr<V4l2Buffer> &buf,
    483     const struct v4l2_format &format,
    484     const uint32_t index)
    485 {
    486     struct v4l2_buffer v4l2_buf;
    487 
    488     xcam_mem_clear (v4l2_buf);
    489     v4l2_buf.index = index;
    490     v4l2_buf.type = _capture_buf_type;
    491     v4l2_buf.memory = _memory_type;
    492 
    493     switch (_memory_type) {
    494     case V4L2_MEMORY_DMABUF:
    495     {
    496         struct v4l2_exportbuffer expbuf;
    497         xcam_mem_clear (expbuf);
    498         expbuf.type = _capture_buf_type;
    499         expbuf.index = index;
    500         expbuf.flags = O_CLOEXEC;
    501         if (io_control (VIDIOC_EXPBUF, &expbuf) < 0) {
    502             XCAM_LOG_WARNING ("device(%s) get dma buf(%d) failed", XCAM_STR (_name), index);
    503             return XCAM_RETURN_ERROR_MEM;
    504         }
    505         v4l2_buf.m.fd = expbuf.fd;
    506         v4l2_buf.length = format.fmt.pix.sizeimage;
    507     }
    508     break;
    509     case V4L2_MEMORY_MMAP:
    510     {
    511         void *pointer;
    512         int map_flags = MAP_SHARED;
    513 #ifdef NEED_MAP_32BIT
    514         map_flags |= MAP_32BIT;
    515 #endif
    516         if (io_control (VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
    517             XCAM_LOG_WARNING("device(%s) query MMAP buf(%d) failed", XCAM_STR(_name), index);
    518             return XCAM_RETURN_ERROR_MEM;
    519         }
    520         pointer = mmap (0, v4l2_buf.length, PROT_READ | PROT_WRITE, map_flags, _fd, v4l2_buf.m.offset);
    521         if (pointer == MAP_FAILED) {
    522             XCAM_LOG_WARNING("device(%s) mmap buf(%d) failed", XCAM_STR(_name), index);
    523             return XCAM_RETURN_ERROR_MEM;
    524         }
    525         v4l2_buf.m.userptr = (uintptr_t) pointer;
    526     }
    527     break;
    528     case V4L2_MEMORY_USERPTR:
    529     default:
    530         XCAM_ASSERT (false);
    531         XCAM_LOG_WARNING (
    532             "device(%s) allocated buffer mem_type(%d) doesn't support",
    533             XCAM_STR (_name), _memory_type);
    534         return XCAM_RETURN_ERROR_MEM;
    535     }
    536 
    537     buf = new V4l2Buffer (v4l2_buf, _format);
    538 
    539     return XCAM_RETURN_NO_ERROR;
    540 }
    541 
    542 XCamReturn
    543 V4l2Device::init_buffer_pool ()
    544 {
    545     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    546     uint32_t i = 0;
    547 
    548     _buf_pool.clear ();
    549     _buf_pool.reserve (_buf_count);
    550 
    551     for (; i < _buf_count; i++) {
    552         SmartPtr<V4l2Buffer> new_buf;
    553         ret = allocate_buffer (new_buf, _format, i);
    554         if (ret != XCAM_RETURN_NO_ERROR) {
    555             break;
    556         }
    557         _buf_pool.push_back (new_buf);
    558     }
    559 
    560     if (_buf_pool.empty()) {
    561         XCAM_LOG_ERROR ("No bufer allocated in device(%s)", XCAM_STR (_name));
    562         return XCAM_RETURN_ERROR_MEM;
    563     }
    564 
    565     if (i != _buf_count) {
    566         XCAM_LOG_WARNING (
    567             "device(%s) allocate buffer count:%d failback to %d",
    568             XCAM_STR (_name), _buf_count, i);
    569         _buf_count = i;
    570     }
    571 
    572     return XCAM_RETURN_NO_ERROR;
    573 }
    574 
    575 XCamReturn
    576 V4l2Device::fini_buffer_pool()
    577 {
    578     _buf_pool.clear ();
    579     return XCAM_RETURN_NO_ERROR;
    580 }
    581 
    582 XCamReturn
    583 V4l2Device::dequeue_buffer(SmartPtr<V4l2Buffer> &buf)
    584 {
    585     struct v4l2_buffer v4l2_buf;
    586 
    587     if (!is_activated()) {
    588         XCAM_LOG_DEBUG (
    589             "device(%s) dequeue buffer failed since not activated", XCAM_STR (_name));
    590         return XCAM_RETURN_ERROR_PARAM;
    591     }
    592 
    593     xcam_mem_clear (v4l2_buf);
    594     v4l2_buf.type = _capture_buf_type;
    595     v4l2_buf.memory = _memory_type;
    596 
    597     if (this->io_control (VIDIOC_DQBUF, &v4l2_buf) < 0) {
    598         XCAM_LOG_ERROR ("device(%s) fail to dequeue buffer.", XCAM_STR (_name));
    599         return XCAM_RETURN_ERROR_IOCTL;
    600     }
    601 
    602     XCAM_LOG_DEBUG ("device(%s) dequeue buffer index:%d", XCAM_STR (_name), v4l2_buf.index);
    603 
    604     if (v4l2_buf.index > _buf_count) {
    605         XCAM_LOG_ERROR (
    606             "device(%s) dequeue wrong buffer index:%d",
    607             XCAM_STR (_name), v4l2_buf.index);
    608         return XCAM_RETURN_ERROR_ISP;
    609     }
    610     buf = _buf_pool [v4l2_buf.index];
    611     buf->set_timestamp (v4l2_buf.timestamp);
    612     buf->set_timecode (v4l2_buf.timecode);
    613     buf->set_sequence (v4l2_buf.sequence);
    614     //buf.set_length (v4l2_buf.length); // not necessary to set length
    615     return XCAM_RETURN_NO_ERROR;
    616 }
    617 
    618 XCamReturn
    619 V4l2Device::queue_buffer (SmartPtr<V4l2Buffer> &buf)
    620 {
    621     XCAM_ASSERT (buf.ptr());
    622     buf->reset ();
    623 
    624     struct v4l2_buffer v4l2_buf = buf->get_buf ();
    625     XCAM_ASSERT (v4l2_buf.index < _buf_count);
    626 
    627     XCAM_LOG_DEBUG ("device(%s) queue buffer index:%d", XCAM_STR (_name), v4l2_buf.index);
    628     if (io_control (VIDIOC_QBUF, &v4l2_buf) < 0) {
    629         XCAM_LOG_ERROR("fail to enqueue buffer index:%d.", v4l2_buf.index);
    630         return XCAM_RETURN_ERROR_IOCTL;
    631     }
    632     return XCAM_RETURN_NO_ERROR;
    633 }
    634 
    635 V4l2SubDevice::V4l2SubDevice (const char *name)
    636     : V4l2Device (name)
    637 {
    638 }
    639 
    640 XCamReturn
    641 V4l2SubDevice::subscribe_event (int event)
    642 {
    643     struct v4l2_event_subscription sub;
    644     int ret = 0;
    645 
    646     XCAM_ASSERT (is_opened());
    647 
    648     xcam_mem_clear (sub);
    649     sub.type = event;
    650 
    651     ret = this->io_control (VIDIOC_SUBSCRIBE_EVENT, &sub);
    652     if (ret < 0) {
    653         XCAM_LOG_DEBUG ("subdev(%s) subscribe event(%d) failed", XCAM_STR(_name), event);
    654         return XCAM_RETURN_ERROR_IOCTL;
    655     }
    656     return XCAM_RETURN_NO_ERROR;
    657 }
    658 
    659 XCamReturn
    660 V4l2SubDevice::unsubscribe_event (int event)
    661 {
    662     struct v4l2_event_subscription sub;
    663     int ret = 0;
    664 
    665     XCAM_ASSERT (is_opened());
    666 
    667     xcam_mem_clear (sub);
    668     sub.type = event;
    669 
    670     ret = this->io_control (VIDIOC_UNSUBSCRIBE_EVENT, &sub);
    671     if (ret < 0) {
    672         XCAM_LOG_DEBUG ("subdev(%s) unsubscribe event(%d) failed", XCAM_STR(_name), event);
    673         return XCAM_RETURN_ERROR_IOCTL;
    674     }
    675     return XCAM_RETURN_NO_ERROR;
    676 }
    677 
    678 XCamReturn
    679 V4l2SubDevice::dequeue_event (struct v4l2_event &event)
    680 {
    681     int ret = 0;
    682     XCAM_ASSERT (is_opened());
    683 
    684     ret = this->io_control (VIDIOC_DQEVENT, &event);
    685     if (ret < 0) {
    686         XCAM_LOG_DEBUG ("subdev(%s) dequeue event failed", XCAM_STR(_name));
    687         return XCAM_RETURN_ERROR_IOCTL;
    688     }
    689 
    690     return XCAM_RETURN_NO_ERROR;
    691 }
    692 
    693 XCamReturn V4l2SubDevice::start ()
    694 {
    695     if (!is_opened())
    696         return XCAM_RETURN_ERROR_PARAM;
    697 
    698     _active = true;
    699     return XCAM_RETURN_NO_ERROR;
    700 }
    701 
    702 XCamReturn V4l2SubDevice::stop ()
    703 {
    704     if (_active)
    705         _active = false;
    706 
    707     return XCAM_RETURN_NO_ERROR;
    708 }
    709 
    710 };
    711