• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@intel.com>
19  * Author: John Ye <john.ye@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 
V4l2Device(const char * name)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 
~V4l2Device()54 V4l2Device::~V4l2Device ()
55 {
56     close();
57     if (_name)
58         xcam_free (_name);
59 }
60 
61 bool
set_device_name(const char * name)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
set_sensor_id(int id)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
set_capture_mode(uint32_t capture_mode)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
set_framerate(uint32_t n,uint32_t d)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
get_framerate(uint32_t & n,uint32_t & d)113 V4l2Device::get_framerate (uint32_t &n, uint32_t &d)
114 {
115     n = _fps_n;
116     d = _fps_d;
117 }
118 
119 bool
set_mem_type(enum v4l2_memory type)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
set_buffer_count(uint32_t buf_count)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
open()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
close()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
io_control(int cmd,void * arg)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
poll_event(int timeout_msec)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
set_format(struct v4l2_format & format)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
set_format(uint32_t width,uint32_t height,uint32_t pixelformat,enum v4l2_field field,uint32_t bytes_perline)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
pre_set_format(struct v4l2_format & format)332 V4l2Device::pre_set_format (struct v4l2_format &format)
333 {
334     XCAM_UNUSED (format);
335     return XCAM_RETURN_NO_ERROR;
336 }
337 
338 XCamReturn
post_set_format(struct v4l2_format & format)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>
enum_formats()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
get_format(struct v4l2_format & format)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
start()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
stop()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
request_buffer()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
allocate_buffer(SmartPtr<V4l2Buffer> & buf,const struct v4l2_format & format,const uint32_t index)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
init_buffer_pool()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
fini_buffer_pool()576 V4l2Device::fini_buffer_pool()
577 {
578     _buf_pool.clear ();
579     return XCAM_RETURN_NO_ERROR;
580 }
581 
582 XCamReturn
dequeue_buffer(SmartPtr<V4l2Buffer> & buf)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
queue_buffer(SmartPtr<V4l2Buffer> & buf)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 
V4l2SubDevice(const char * name)635 V4l2SubDevice::V4l2SubDevice (const char *name)
636     : V4l2Device (name)
637 {
638 }
639 
640 XCamReturn
subscribe_event(int event)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
unsubscribe_event(int event)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
dequeue_event(struct v4l2_event & event)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 
start()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 
stop()702 XCamReturn V4l2SubDevice::stop ()
703 {
704     if (_active)
705         _active = false;
706 
707     return XCAM_RETURN_NO_ERROR;
708 }
709 
710 };
711