xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkaiq/xcore/v4l2_device.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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  4
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     , _buf_type (V4L2_BUF_TYPE_VIDEO_CAPTURE)
43     , _buf_sync (false)
44     , _memory_type (V4L2_MEMORY_MMAP)
45     , _planes (NULL)
46     , _fps_n (0)
47     , _fps_d (0)
48     , _active (false)
49     , _buf_count (XCAM_V4L2_DEFAULT_BUFFER_COUNT)
50     , _queued_bufcnt(0)
51     ,_mplanes_count(FMT_NUM_PLANES)
52 {
53     if (name)
54         _name = strndup (name, XCAM_MAX_STR_SIZE);
55     xcam_mem_clear (_format);
56 }
57 
~V4l2Device()58 V4l2Device::~V4l2Device ()
59 {
60     close();
61     if (_name)
62         xcam_free (_name);
63     if (_planes)
64         xcam_free (_planes);
65 }
66 
67 bool
set_device_name(const char * name)68 V4l2Device::set_device_name (const char *name)
69 {
70     XCAM_ASSERT (name);
71 
72     if (is_opened()) {
73         XCAM_LOG_WARNING ("can't set device name since device opened");
74         return false;
75     }
76     if (_name)
77         xcam_free (_name);
78     _name = strndup (name, XCAM_MAX_STR_SIZE);
79     return true;
80 }
81 
82 bool
set_sensor_id(int id)83 V4l2Device::set_sensor_id (int id)
84 {
85     if (is_opened()) {
86         XCAM_LOG_WARNING ("can't set sensor id since device opened");
87         return false;
88     }
89     _sensor_id = id;
90     return true;
91 }
92 
93 bool
set_capture_mode(uint32_t capture_mode)94 V4l2Device::set_capture_mode (uint32_t capture_mode)
95 {
96     if (is_opened()) {
97         XCAM_LOG_WARNING ("can't set sensor id since device opened");
98         return false;
99     }
100     _capture_mode = capture_mode;
101     return true;
102 }
103 
104 bool
set_mplanes_count(uint32_t planes_count)105 V4l2Device::set_mplanes_count (uint32_t planes_count)
106 {
107     if (is_activated ()) {
108         XCAM_LOG_WARNING ("device(%s) set mplanes count failed", XCAM_STR (_name));
109         return false;
110     }
111     _mplanes_count = planes_count;
112     return true;
113 }
114 
115 bool
set_framerate(uint32_t n,uint32_t d)116 V4l2Device::set_framerate (uint32_t n, uint32_t d)
117 {
118     if (_format.fmt.pix.pixelformat) {
119         XCAM_LOG_WARNING ("device(%s) set framerate failed since formatted was already set.", XCAM_STR(_name));
120         return false;
121     }
122 
123     _fps_n = n;
124     _fps_d = d;
125 
126     return true;
127 }
128 
129 void
get_framerate(uint32_t & n,uint32_t & d)130 V4l2Device::get_framerate (uint32_t &n, uint32_t &d)
131 {
132     n = _fps_n;
133     d = _fps_d;
134 }
135 
136 bool
set_mem_type(enum v4l2_memory type)137 V4l2Device::set_mem_type (enum v4l2_memory type) {
138     if (is_activated ()) {
139         XCAM_LOG_WARNING ("device(%s) set mem type failed", XCAM_STR (_name));
140         return false;
141     }
142     _memory_type = type;
143     return true;
144 }
145 
146 bool
set_buf_type(enum v4l2_buf_type type)147 V4l2Device::set_buf_type (enum v4l2_buf_type type) {
148     if (is_activated ()) {
149         XCAM_LOG_WARNING ("device(%s) set buf type failed", XCAM_STR (_name));
150         return false;
151     }
152     _buf_type = type;
153     return true;
154 }
155 
156 bool
set_buf_sync(bool sync)157 V4l2Device::set_buf_sync (bool sync) {
158     if (is_activated ()) {
159         XCAM_LOG_WARNING ("device(%s) set buf sync failed", XCAM_STR (_name));
160         return false;
161     }
162     _buf_sync = sync;
163     return true;
164 }
165 
166 bool
set_buffer_count(uint32_t buf_count)167 V4l2Device::set_buffer_count (uint32_t buf_count)
168 {
169     if (is_activated ()) {
170         XCAM_LOG_WARNING ("device(%s) set buffer count failed", XCAM_STR (_name));
171         return false;
172     }
173 
174     _buf_count = buf_count;
175 
176     return true;
177 }
178 
179 
180 XCamReturn
open(bool nonblock)181 V4l2Device::open (bool nonblock)
182 {
183     struct v4l2_streamparm param;
184 
185     if (is_opened()) {
186         XCAM_LOG_DEBUG ("device(%s) was already opened", XCAM_STR(_name));
187         return XCAM_RETURN_NO_ERROR;
188     }
189 
190     if (!_name) {
191         XCAM_LOG_DEBUG ("v4l2 device open failed, there's no device name");
192         return XCAM_RETURN_ERROR_PARAM;
193     }
194     if (nonblock)
195         _fd = ::open (_name, O_RDWR | O_CLOEXEC | O_NONBLOCK);
196     else
197         _fd = ::open (_name, O_RDWR | O_CLOEXEC);
198     if (_fd == -1) {
199         XCAM_LOG_ERROR ("open device(%s) failed", _name);
200         return XCAM_RETURN_ERROR_IOCTL;
201     } else {
202         XCAM_LOG_DEBUG ("open device(%s) successed, fd: %d", _name, _fd);
203     }
204 #if 0
205     // set sensor id
206     if (io_control (VIDIOC_S_INPUT, &_sensor_id) < 0) {
207         XCAM_LOG_WARNING ("set sensor id(%d) failed but continue", _sensor_id);
208     }
209 
210     // set capture mode
211     xcam_mem_clear (param);
212     param.type = _buf_type;
213     param.parm.capture.capturemode = _capture_mode;
214     if (io_control (VIDIOC_S_PARM, &param) < 0) {
215         XCAM_LOG_WARNING ("set capture mode(0x%08x) failed but continue", _capture_mode);
216     }
217 #endif
218     struct v4l2_capability cap;
219     // only video node cay query cap
220     if (_name && strstr(_name, "video")) {
221         query_cap(cap);
222         // get default foramt
223         get_format (_format);
224     }
225 
226     if (_buf_type == V4L2_BUF_TYPE_META_CAPTURE)
227         _buf_sync = true;
228 
229     return XCAM_RETURN_NO_ERROR;
230 }
231 
232 XCamReturn
close()233 V4l2Device::close ()
234 {
235     if (!is_opened())
236         return XCAM_RETURN_NO_ERROR;
237     ::close (_fd);
238     _fd = -1;
239 
240     XCAM_LOG_INFO ("device(%s) closed", XCAM_STR (_name));
241     return XCAM_RETURN_NO_ERROR;
242 }
243 
244 int
io_control(unsigned long cmd,void * arg)245 V4l2Device::io_control (unsigned long cmd, void *arg)
246 
247 {
248     if (_fd <= 0)
249         return -1;
250 
251     return xcam_device_ioctl (_fd, cmd, arg);
252 }
253 
254 int
poll_event(int timeout_msec,int stop_fd)255 V4l2Device::poll_event (int timeout_msec, int stop_fd)
256 {
257     int num_fds = stop_fd == -1 ? 1 : 2;
258     struct pollfd poll_fds[num_fds];
259     int ret = 0;
260 
261     XCAM_ASSERT (_fd > 0);
262 
263     memset(poll_fds, 0, sizeof(poll_fds));
264     poll_fds[0].fd = _fd;
265     poll_fds[0].events = (POLLPRI | POLLIN | POLLOUT | POLLERR | POLLNVAL | POLLHUP);
266 
267     if (stop_fd != -1) {
268         poll_fds[1].fd = stop_fd;
269         poll_fds[1].events = POLLPRI | POLLIN | POLLOUT;
270         poll_fds[1].revents = 0;
271     }
272 
273     ret = poll (poll_fds, num_fds, timeout_msec);
274     if (stop_fd != -1) {
275         if ((poll_fds[1].revents & POLLIN) || (poll_fds[1].revents & POLLPRI)) {
276             XCAM_LOG_DEBUG ("%s: Poll returning from flush", __FUNCTION__);
277             return POLL_STOP_RET;
278         }
279     }
280 
281     if (ret > 0 && (poll_fds[0].revents & (POLLERR | POLLNVAL | POLLHUP))) {
282         XCAM_LOG_DEBUG ("v4l2 subdev(%s) polled error", XCAM_STR(_name));
283         return -1;
284     }
285 
286     return ret;
287 
288 }
289 
290 XCamReturn
query_cap(struct v4l2_capability & cap)291 V4l2Device::query_cap (struct v4l2_capability &cap)
292 {
293     int ret = 0;
294 
295     XCAM_FAIL_RETURN (ERROR, is_opened (), XCAM_RETURN_ERROR_FILE,
296                       "Cannot query cap from v4l2 device while it is closed.");
297 
298     ret = io_control(VIDIOC_QUERYCAP, &cap);
299 
300     if (ret < 0) {
301         XCAM_LOG_ERROR("VIDIOC_QUERYCAP returned: %d (%s)", ret, strerror(errno));
302         return XCAM_RETURN_ERROR_UNKNOWN;
303     }
304 
305     if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
306         _buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
307     else if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
308         _buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
309     else if (cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)
310         _buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
311     else if (cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)
312         _buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
313     else if (cap.capabilities & V4L2_CAP_META_CAPTURE)
314         _buf_type = V4L2_BUF_TYPE_META_CAPTURE;
315     else if (cap.capabilities & V4L2_CAP_META_OUTPUT)
316         _buf_type = V4L2_BUF_TYPE_META_OUTPUT;
317     else {
318         XCAM_LOG_ERROR("@%s: unsupported buffer type.", __FUNCTION__);
319         return XCAM_RETURN_ERROR_UNKNOWN;
320     }
321 
322     XCAM_LOG_INFO("------------------------------");
323     XCAM_LOG_INFO("driver:       '%s'", cap.driver);
324     XCAM_LOG_INFO("card:         '%s'", cap.card);
325     XCAM_LOG_INFO("bus_info:     '%s'", cap.bus_info);
326     XCAM_LOG_INFO("version:      %x", cap.version);
327     XCAM_LOG_INFO("capabilities: %x", cap.capabilities);
328     XCAM_LOG_INFO("device caps:  %x", cap.device_caps);
329     XCAM_LOG_INFO("buffer type   %d", _buf_type);
330     XCAM_LOG_INFO("------------------------------");
331 
332     return XCAM_RETURN_NO_ERROR;
333 }
334 
335 XCamReturn
set_format(struct v4l2_format & format)336 V4l2Device::set_format (struct v4l2_format &format)
337 {
338     XCamReturn ret = XCAM_RETURN_NO_ERROR;
339 
340     XCAM_FAIL_RETURN (ERROR, !is_activated (), XCAM_RETURN_ERROR_PARAM,
341                       "Cannot set format to v4l2 device while it is active.");
342 
343     XCAM_FAIL_RETURN (ERROR, is_opened (), XCAM_RETURN_ERROR_FILE,
344                       "Cannot set format to v4l2 device while it is closed.");
345 
346     struct v4l2_format tmp_format = format;
347 
348     ret = pre_set_format (format);
349     if (ret != XCAM_RETURN_NO_ERROR) {
350         XCAM_LOG_WARNING ("device(%s) pre_set_format failed", XCAM_STR (_name));
351         //RKTODO::rkisp no need to do set format op for subdev.
352         //return ret;
353     }
354 
355     if (io_control (VIDIOC_S_FMT, &format) < 0) {
356         if (errno == EBUSY) {
357             // TODO log device name
358             XCAM_LOG_ERROR("Video device is busy, fail to set format.");
359         } else {
360             // TODO log format details and errno
361             XCAM_LOG_ERROR("Fail to set format: %s", strerror(errno));
362         }
363 
364         return XCAM_RETURN_ERROR_IOCTL;
365     }
366 
367     if (tmp_format.fmt.pix.width != format.fmt.pix.width || tmp_format.fmt.pix.height != format.fmt.pix.height) {
368         XCAM_LOG_ERROR (
369             "device(%s) set v4l2 format failed, supported format: width:%d, height:%d",
370             XCAM_STR (_name),
371             format.fmt.pix.width,
372             format.fmt.pix.height);
373 
374         return XCAM_RETURN_ERROR_PARAM;
375     }
376 
377     while (_fps_n && _fps_d) {
378         struct v4l2_streamparm param;
379         xcam_mem_clear (param);
380         param.type = _buf_type;
381         if (io_control (VIDIOC_G_PARM, &param) < 0) {
382             XCAM_LOG_WARNING ("device(%s) set framerate failed on VIDIOC_G_PARM but continue", XCAM_STR (_name));
383             break;
384         }
385 
386         if (!(param.parm.capture.capability & V4L2_CAP_TIMEPERFRAME))
387             break;
388 
389         param.parm.capture.timeperframe.numerator = _fps_d;
390         param.parm.capture.timeperframe.denominator = _fps_n;
391 
392         if (io_control (VIDIOC_S_PARM, &param) < 0) {
393             XCAM_LOG_WARNING ("device(%s) set framerate failed on VIDIOC_S_PARM but continue", XCAM_STR (_name));
394             break;
395         }
396         _fps_n = param.parm.capture.timeperframe.denominator;
397         _fps_d = param.parm.capture.timeperframe.numerator;
398         XCAM_LOG_INFO ("device(%s) set framerate(%d/%d)", XCAM_STR (_name), _fps_n, _fps_d);
399 
400         // exit here, otherwise it is an infinite loop
401         break;
402     }
403 
404     ret = post_set_format (format);
405     if (ret != XCAM_RETURN_NO_ERROR) {
406         XCAM_LOG_WARNING ("device(%s) post_set_format failed", XCAM_STR (_name));
407         return ret;
408     }
409 
410     _format = format;
411     XCAM_LOG_INFO (
412         "device(%s) set format(w:%d, h:%d, pixelformat:%s, bytesperline:%d,image_size:%d)",
413         XCAM_STR (_name),
414         format.fmt.pix.width, format.fmt.pix.height,
415         xcam_fourcc_to_string (format.fmt.pix.pixelformat),
416         format.fmt.pix.bytesperline,
417         format.fmt.pix.sizeimage);
418 
419     return XCAM_RETURN_NO_ERROR;
420 }
421 
422 /*! \brief v4l2 set format
423  *
424  * \param[in]    width            format width
425  * \param[in]    height           format height
426  * \param[in]    pixelformat      fourcc
427  * \param[in]    field            V4L2_FIELD_INTERLACED or V4L2_FIELD_NONE
428  */
429 XCamReturn
set_format(uint32_t width,uint32_t height,uint32_t pixelformat,enum v4l2_field field,uint32_t bytes_perline)430 V4l2Device::set_format (
431     uint32_t width,  uint32_t height,
432     uint32_t pixelformat, enum v4l2_field field, uint32_t bytes_perline)
433 {
434     XCAM_LOG_INFO (
435         "device(%s) set format(w:%d, h:%d, pixelformat:%s, bytesperline:%d)",
436         XCAM_STR (_name),
437         width, height,
438         xcam_fourcc_to_string (pixelformat),
439         bytes_perline);
440 
441     struct v4l2_format format;
442     xcam_mem_clear (format);
443 
444     format.type = _buf_type;
445     format.fmt.pix.width = width;
446     format.fmt.pix.height = height;
447     format.fmt.pix.pixelformat = pixelformat;
448     format.fmt.pix.field = field;
449 
450     if (bytes_perline != 0)
451         format.fmt.pix.bytesperline = bytes_perline;
452     return set_format (format);
453 }
454 
455 XCamReturn
pre_set_format(struct v4l2_format & format)456 V4l2Device::pre_set_format (struct v4l2_format &format)
457 {
458     XCAM_UNUSED (format);
459     return XCAM_RETURN_NO_ERROR;
460 }
461 
462 XCamReturn
post_set_format(struct v4l2_format & format)463 V4l2Device::post_set_format (struct v4l2_format &format)
464 {
465     XCAM_UNUSED (format);
466     return XCAM_RETURN_NO_ERROR;
467 }
468 
469 std::list<struct v4l2_fmtdesc>
enum_formats()470 V4l2Device::enum_formats ()
471 {
472     std::list<struct v4l2_fmtdesc> formats;
473     struct v4l2_fmtdesc format;
474     uint32_t i = 0;
475 
476     while (1) {
477         xcam_mem_clear (format);
478         format.index = i++;
479         format.type = _buf_type;
480         if (this->io_control (VIDIOC_ENUM_FMT, &format) < 0) {
481             if (errno == EINVAL)
482                 break;
483             else { // error
484                 XCAM_LOG_DEBUG ("enum formats failed");
485                 return formats;
486             }
487         }
488         formats.push_back (format);
489     }
490 
491     return formats;
492 }
493 
494 XCamReturn
get_format(struct v4l2_format & format)495 V4l2Device::get_format (struct v4l2_format &format)
496 {
497     if (is_activated ()) {
498         format = _format;
499         return XCAM_RETURN_NO_ERROR;
500     }
501 
502     if (!is_opened ())
503         return XCAM_RETURN_ERROR_IOCTL;
504 
505     xcam_mem_clear (format);
506     format.type = _buf_type;
507 
508     if (this->io_control (VIDIOC_G_FMT, &format) < 0) {
509         // FIXME: also log the device name?
510         XCAM_LOG_ERROR("Fail to get format via ioctl VIDVIO_G_FMT.");
511         return XCAM_RETURN_ERROR_IOCTL;
512     }
513 
514     return XCAM_RETURN_NO_ERROR;
515 }
516 
517 XCamReturn
prepare()518 V4l2Device::prepare ()
519 {
520     XCamReturn ret = XCAM_RETURN_NO_ERROR;
521     // request buffer first
522     ret = request_buffer ();
523     XCAM_FAIL_RETURN (
524         ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
525         "device(%s) start failed", XCAM_STR (_name));
526     _queued_bufcnt = 0;
527     //alloc buffers
528     ret = init_buffer_pool ();
529     XCAM_FAIL_RETURN (
530         ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
531         "device(%s) start failed", XCAM_STR (_name));
532 #ifndef USE_RAWSTREAM_LIB
533     if (!V4L2_TYPE_IS_OUTPUT(_buf_type) &&
534             (_buf_type != V4L2_BUF_TYPE_META_OUTPUT)) {
535 #else
536     if (!V4L2_TYPE_IS_OUTPUT(_buf_type) && (_memory_type != V4L2_MEMORY_DMABUF) &&
537             (_buf_type != V4L2_BUF_TYPE_META_OUTPUT)) {
538 #endif
539         //queue all buffers
540         for (uint32_t i = 0; i < _buf_count; ++i) {
541             SmartPtr<V4l2Buffer> &buf = _buf_pool [i];
542             XCAM_ASSERT (buf.ptr());
543             XCAM_ASSERT (buf->get_buf().index == i);
544             ret = queue_buffer (buf);
545             if (ret != XCAM_RETURN_NO_ERROR) {
546                 XCAM_LOG_ERROR (
547                     "device(%s) start failed on queue index:%d",
548                     XCAM_STR (_name), i);
549                 stop ();
550                 return ret;
551             }
552         }
553     }
554     return ret;
555 }
556 
557 XCamReturn
558 V4l2Device::get_crop (struct v4l2_crop &crop)
559 {
560     int ret = 0;
561     XCAM_ASSERT (is_opened());
562     ret = this->io_control (VIDIOC_G_CROP, &crop);
563     if (ret < 0) {
564         XCAM_LOG_ERROR("subdev(%s) VIDIOC_G_CROP failed", XCAM_STR(_name));
565         return XCAM_RETURN_ERROR_IOCTL;
566     }
567     return XCAM_RETURN_NO_ERROR;
568 }
569 
570 XCamReturn
571 V4l2Device::set_selection (struct v4l2_selection &select)
572 {
573     int ret = 0;
574     XCAM_ASSERT (is_opened());
575     ret = this->io_control (VIDIOC_S_SELECTION, &select);
576     if (ret < 0) {
577         XCAM_LOG_ERROR("videodev (%s) VIDIOC_S_SELECTION failed", XCAM_STR(_name));
578         return XCAM_RETURN_ERROR_IOCTL;
579     }
580     return XCAM_RETURN_NO_ERROR;
581 }
582 
583 XCamReturn
584 V4l2Device::set_crop (struct v4l2_crop &crop)
585 {
586     int ret = 0;
587     XCAM_ASSERT (is_opened());
588     ret = this->io_control (VIDIOC_S_CROP, &crop);
589     if (ret < 0) {
590         XCAM_LOG_ERROR("subdev(%s) VIDIOC_S_CROP failed", XCAM_STR(_name));
591         return XCAM_RETURN_ERROR_IOCTL;
592     }
593     return XCAM_RETURN_NO_ERROR;
594 }
595 
596 XCamReturn
597 V4l2SubDevice::set_selection (struct v4l2_subdev_selection &aSelection)
598 {
599     int ret = 0;
600     XCAM_ASSERT (is_opened());
601 
602     XCAM_LOG_DEBUG ("VIDIOC_SUBDEV_S_SELECTION: which: %d, pad: %d, target: 0x%x, "
603          "flags: 0x%x, rect left: %d, rect top: %d, width: %d, height: %d",
604         aSelection.which,
605         aSelection.pad,
606         aSelection.target,
607         aSelection.flags,
608         aSelection.r.left,
609         aSelection.r.top,
610         aSelection.r.width,
611         aSelection.r.height);
612 
613     ret = this->io_control (VIDIOC_SUBDEV_S_SELECTION, &aSelection);
614     if (ret < 0) {
615         XCAM_LOG_ERROR("subdev(%s) VIDIOC_SUBDEV_S_SELECTION failed", XCAM_STR(_name));
616         return XCAM_RETURN_ERROR_IOCTL;
617     }
618 
619     return XCAM_RETURN_NO_ERROR;
620 }
621 
622 XCamReturn
623 V4l2SubDevice::getFormat(struct v4l2_subdev_format &aFormat)
624 {
625     int ret = 0;
626     XCAM_ASSERT (is_opened());
627 
628     ret = this->io_control(VIDIOC_SUBDEV_G_FMT, &aFormat);
629     if (ret < 0) {
630         XCAM_LOG_ERROR("subdev(%s) VIDIOC_SUBDEV_G_FMT failed: %s", XCAM_STR(_name));
631         return XCAM_RETURN_ERROR_IOCTL;
632     }
633 
634     XCAM_LOG_DEBUG ("VIDIOC_SUBDEV_G_FMT: pad: %d, which: %d, width: %d, "
635          "height: %d, format: 0x%x, field: %d, color space: %d",
636          aFormat.pad,
637          aFormat.which,
638          aFormat.format.width,
639          aFormat.format.height,
640          aFormat.format.code,
641          aFormat.format.field,
642          aFormat.format.colorspace);
643 
644     return XCAM_RETURN_NO_ERROR;
645 }
646 
647 XCamReturn
648 V4l2SubDevice::setFormat(struct v4l2_subdev_format &aFormat)
649 {
650     int ret = 0;
651     XCAM_ASSERT (is_opened());
652 
653     XCAM_LOG_DEBUG ("VIDIOC_SUBDEV_S_FMT: pad: %d, which: %d, width: %d, "
654          "height: %d, format: 0x%x, field: %d, color space: %d",
655          aFormat.pad,
656          aFormat.which,
657          aFormat.format.width,
658          aFormat.format.height,
659          aFormat.format.code,
660          aFormat.format.field,
661          aFormat.format.colorspace);
662 
663     ret = this->io_control(VIDIOC_SUBDEV_S_FMT, &aFormat);
664     if (ret < 0) {
665         XCAM_LOG_ERROR("subdev(%s) VIDIOC_SUBDEV_S_FMT failed: %s", XCAM_STR(_name));
666         return XCAM_RETURN_ERROR_IOCTL;
667     }
668 
669     return XCAM_RETURN_NO_ERROR;
670 }
671 
672 XCamReturn
673 V4l2Device::start (bool prepared)
674 {
675     XCamReturn ret = XCAM_RETURN_NO_ERROR;
676     if (!prepared) {
677         // request buffer first
678         ret = request_buffer ();
679         XCAM_FAIL_RETURN (
680             ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
681             "device(%s) start failed", XCAM_STR (_name));
682         _queued_bufcnt = 0;
683         //alloc buffers
684         ret = init_buffer_pool ();
685         XCAM_FAIL_RETURN (
686             ERROR, ret == XCAM_RETURN_NO_ERROR, ret,
687             "device(%s) start failed", XCAM_STR (_name));
688         if (!V4L2_TYPE_IS_OUTPUT(_buf_type) &&
689                 (_buf_type != V4L2_BUF_TYPE_META_OUTPUT)) {
690             //queue all buffers
691             for (uint32_t i = 0; i < _buf_count; ++i) {
692                 SmartPtr<V4l2Buffer> &buf = _buf_pool [i];
693                 XCAM_ASSERT (buf.ptr());
694                 XCAM_ASSERT (buf->get_buf().index == i);
695                 ret = queue_buffer (buf);
696                 if (ret != XCAM_RETURN_NO_ERROR) {
697                     XCAM_LOG_ERROR (
698                         "device(%s) start failed on queue index:%d",
699                         XCAM_STR (_name), i);
700                     stop ();
701                     return ret;
702                 }
703             }
704         }
705     }
706     // stream on
707     if (io_control (VIDIOC_STREAMON, &_buf_type) < 0) {
708         XCAM_LOG_ERROR (
709             "device(%s) start failed on VIDIOC_STREAMON, fd=%d",
710             XCAM_STR (_name), _fd);
711         stop ();
712         return XCAM_RETURN_ERROR_IOCTL;
713     }
714     _active = true;
715     XCAM_LOG_INFO ("device(%s) started successfully", XCAM_STR (_name));
716     return XCAM_RETURN_NO_ERROR;
717 }
718 
719 XCamReturn
720 V4l2Device::stop_streamoff ()
721 {
722     SmartLock auto_lock(_buf_mutex);
723     XCAM_LOG_INFO ("device(%s) stop stream off", XCAM_STR (_name));
724     // stream off
725     if (_active) {
726         if (io_control (VIDIOC_STREAMOFF, &_buf_type) < 0) {
727             XCAM_LOG_WARNING ("device(%s) steamoff failed", XCAM_STR (_name));
728         }
729         _active = false;
730     }
731     return XCAM_RETURN_NO_ERROR;
732 }
733 
734 XCamReturn
735 V4l2Device::stop_freebuffer ()
736 {
737     SmartLock auto_lock(_buf_mutex);
738     XCAM_LOG_INFO ("device(%s) stop free buffer", XCAM_STR (_name));
739     if (_buf_pool.size() > 0)
740         fini_buffer_pool ();
741     return XCAM_RETURN_NO_ERROR;
742 }
743 
744 XCamReturn
745 V4l2Device::stop ()
746 {
747     SmartLock auto_lock(_buf_mutex);
748     XCAM_LOG_INFO ("device(%s) stop, already start: %d", XCAM_STR (_name), _active);
749 
750     // stream off
751     if (_active) {
752         if (io_control (VIDIOC_STREAMOFF, &_buf_type) < 0) {
753             XCAM_LOG_WARNING ("device(%s) steamoff failed", XCAM_STR (_name));
754         }
755         _active = false;
756         /* while (_queued_bufcnt > 0) { */
757         /*     struct v4l2_buffer v4l2_buf; */
758         /*     struct v4l2_plane planes[_mplanes_count]; */
759 
760         /*     xcam_mem_clear (v4l2_buf); */
761         /*     v4l2_buf.type = _buf_type; */
762         /*     v4l2_buf.memory = _memory_type; */
763 
764         /*     if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type || */
765         /*             V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) { */
766         /*         memset(planes, 0, sizeof(struct v4l2_plane) * _mplanes_count); */
767         /*         v4l2_buf.m.planes = planes; */
768         /*         v4l2_buf.length = _mplanes_count; */
769         /*     } */
770 
771         /*     if (this->io_control (VIDIOC_DQBUF, &v4l2_buf) < 0) { */
772         /*         XCAM_LOG_WARNING ("device(%s) fail to dequeue buffer.", XCAM_STR (_name)); */
773         /*     } */
774         /*     _queued_bufcnt--; */
775         /* } */
776         /* fini_buffer_pool (); */
777         /* release the shared buf between mipi tx and rx */
778 #if 0 // moved to fini_buffer_pool, buffer may be requested at prepare stage
779         if (_memory_type == V4L2_MEMORY_DMABUF) {
780             struct v4l2_requestbuffers request_buf;
781             xcam_mem_clear (request_buf);
782             request_buf.type = _buf_type;
783             request_buf.count = 0;
784             request_buf.memory = _memory_type;
785             if (io_control (VIDIOC_REQBUFS, &request_buf) < 0) {
786                 XCAM_LOG_ERROR ("device(%s) starts failed on VIDIOC_REQBUFS", XCAM_STR (_name));
787                 //return XCAM_RETURN_ERROR_IOCTL;
788             }
789         }
790 #endif
791     }
792 
793     if (_buf_pool.size() > 0)
794         fini_buffer_pool ();
795     return XCAM_RETURN_NO_ERROR;
796 }
797 
798 XCamReturn
799 V4l2Device::request_buffer ()
800 {
801     struct v4l2_requestbuffers request_buf;
802 
803     XCAM_ASSERT (!is_activated());
804 
805     xcam_mem_clear (request_buf);
806     request_buf.type = _buf_type;
807     request_buf.count = _buf_count;
808     request_buf.memory = _memory_type;
809 
810     XCAM_LOG_INFO ("request buffers in device(%s): type: %d, count: %d, mem_type: %d",
811                    XCAM_STR (_name),
812                    request_buf.type,
813                    request_buf.count,
814                    request_buf.memory);
815 
816     if (io_control (VIDIOC_REQBUFS, &request_buf) < 0) {
817         XCAM_LOG_INFO ("device(%s) starts failed on VIDIOC_REQBUFS", XCAM_STR (_name));
818         return XCAM_RETURN_ERROR_IOCTL;
819     }
820 
821     XCAM_LOG_INFO ("device(%s) request buffer count: %d",
822                    XCAM_STR (_name), request_buf.count);
823 
824     if (request_buf.count != _buf_count) {
825         XCAM_LOG_INFO (
826             "device(%s) request buffer count doesn't match user settings, reset buffer count to %d",
827             XCAM_STR (_name), request_buf.count);
828         _buf_count = request_buf.count;
829     }
830 
831     if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
832             V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type)
833         _planes = (struct v4l2_plane *)xcam_malloc0
834                   (_buf_count * _mplanes_count * sizeof(struct v4l2_plane));
835 
836     return XCAM_RETURN_NO_ERROR;
837 }
838 
839 XCamReturn
840 V4l2Device::allocate_buffer (
841     SmartPtr<V4l2Buffer> &buf,
842     const struct v4l2_format &format,
843     const uint32_t index)
844 {
845     struct v4l2_buffer v4l2_buf;
846     int expbuf_fd = -1;
847     uintptr_t expbuf_ptr = 0;
848 
849     xcam_mem_clear (v4l2_buf);
850     v4l2_buf.index = index;
851     v4l2_buf.type = _buf_type;
852     v4l2_buf.memory = _memory_type;
853     if (_buf_sync) {
854         v4l2_buf.flags = V4L2_BUF_FLAG_NO_CACHE_INVALIDATE |
855             V4L2_BUF_FLAG_NO_CACHE_CLEAN;
856     }
857 
858     if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
859             V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
860         v4l2_buf.m.planes = &_planes[index * _mplanes_count];
861         v4l2_buf.length = _mplanes_count;
862     }
863 
864     switch (_memory_type) {
865     case V4L2_MEMORY_DMABUF:
866     {
867         v4l2_buf.length = format.fmt.pix.sizeimage;
868         if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
869                 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
870             v4l2_buf.length = _mplanes_count;
871             for (int i=0; i<_mplanes_count; i++) {
872                 v4l2_buf.m.planes[i].length = format.fmt.pix.sizeimage;
873                 v4l2_buf.m.planes[i].bytesused = format.fmt.pix.sizeimage;
874             }
875         }
876     }
877     break;
878     case V4L2_MEMORY_MMAP:
879     {
880         void *pointer = MAP_FAILED;
881         int map_flags = MAP_SHARED;
882 #ifdef NEED_MAP_32BIT
883         map_flags |= MAP_32BIT;
884 #endif
885         if (io_control (VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
886             XCAM_LOG_ERROR("device(%s) query MMAP buf(%d) failed", XCAM_STR(_name), index);
887             return XCAM_RETURN_ERROR_MEM;
888         }
889 
890         if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
891                 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
892             for (int i=0; i<_mplanes_count; i++) {
893                 XCAM_LOG_DEBUG ("device(%s) get planar(%d) of buf(%d) length: %d", XCAM_STR (_name), i, index, v4l2_buf.m.planes[i].length);
894                 pointer = mmap (0, v4l2_buf.m.planes[i].length, PROT_READ | PROT_WRITE, map_flags, _fd, v4l2_buf.m.planes[i].m.mem_offset);
895                 v4l2_buf.m.planes[i].m.userptr = (uintptr_t) pointer;
896                 if (pointer == MAP_FAILED) {
897                     XCAM_LOG_ERROR("device(%s) mmap planar(%d) of buf(%d) failed", XCAM_STR(_name), i, index);
898                     return XCAM_RETURN_ERROR_MEM;
899                 }
900             }
901             expbuf_ptr = v4l2_buf.m.planes[0].m.userptr;
902         } else {
903             XCAM_LOG_DEBUG ("device(%s) get buf(%d) length: %d", XCAM_STR (_name), index, v4l2_buf.length);
904             pointer = mmap (0, v4l2_buf.length, PROT_READ | PROT_WRITE, map_flags, _fd, v4l2_buf.m.offset);
905             if (pointer == MAP_FAILED) {
906                 XCAM_LOG_ERROR("device(%s) mmap buf(%d) failed", XCAM_STR(_name), index);
907                 return XCAM_RETURN_ERROR_MEM;
908             }
909             expbuf_ptr = v4l2_buf.m.userptr = (uintptr_t) pointer;
910         }
911 
912         // export buf dma fd
913         struct v4l2_exportbuffer expbuf;
914         xcam_mem_clear (expbuf);
915         expbuf.type = _buf_type;
916         expbuf.index = index;
917         expbuf.flags = O_CLOEXEC;
918         if (io_control (VIDIOC_EXPBUF, &expbuf) < 0) {
919             XCAM_LOG_ERROR ("device(%s) get dma buf(%d) failed", XCAM_STR (_name), index);
920             return XCAM_RETURN_ERROR_MEM;
921         } else {
922             XCAM_LOG_INFO ("device(%s) get dma buf(%d)-fd: %d", XCAM_STR (_name), index, expbuf.fd);
923         }
924         expbuf_fd = expbuf.fd;
925     }
926     break;
927     case V4L2_MEMORY_USERPTR:
928     {
929        v4l2_buf.length = format.fmt.pix.sizeimage;
930       if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
931           V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
932             v4l2_buf.length = _mplanes_count;
933             for (int i=0; i<_mplanes_count; i++) {
934                 v4l2_buf.m.planes[i].length = format.fmt.pix.sizeimage;
935                 v4l2_buf.m.planes[i].bytesused = format.fmt.pix.sizeimage;
936             }
937       }
938     }
939     break;
940     default:
941         XCAM_ASSERT (false);
942         XCAM_LOG_WARNING (
943             "device(%s) allocated buffer mem_type(%d) doesn't support",
944             XCAM_STR (_name), _memory_type);
945         return XCAM_RETURN_ERROR_MEM;
946     }
947 
948     buf = new V4l2Buffer (v4l2_buf, _format);
949     if (expbuf_fd != -1)
950         buf->set_expbuf_fd (expbuf_fd);
951     if (expbuf_ptr != 0)
952         buf->set_expbuf_usrptr(expbuf_ptr);
953     return XCAM_RETURN_NO_ERROR;
954 }
955 
956 XCamReturn
957 V4l2Device::release_buffer (SmartPtr<V4l2Buffer> &buf)
958 {
959     int ret = 0;
960     switch (_memory_type) {
961     case V4L2_MEMORY_DMABUF:
962     {
963     }
964     break;
965     case V4L2_MEMORY_MMAP:
966     {
967         if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
968                 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
969             for (int i=0; i<_mplanes_count; i++) {
970                 XCAM_LOG_DEBUG("release multi planar(%d) of buffer length: %d", i, buf->get_buf().m.planes[i].length);
971                 ret = munmap((void*)buf->get_buf().m.planes[i].m.userptr, buf->get_buf().m.planes[i].length);
972             }
973             ::close(buf->get_expbuf_fd());
974         } else {
975             XCAM_LOG_DEBUG("release buffer length: %d", buf->get_buf().length);
976             ret = munmap((void*)buf->get_buf().m.userptr, buf->get_buf().length);
977             ::close(buf->get_expbuf_fd());
978         }
979         if (ret != 0) {
980             XCAM_LOG_ERROR (
981                 "release buffer: munmap failed");
982         }
983     }
984     break;
985     case V4L2_MEMORY_USERPTR:
986     break;
987     default:
988         XCAM_ASSERT (false);
989         XCAM_LOG_WARNING (
990             "device(%s) allocated buffer mem_type(%d) doesn't support",
991             XCAM_STR (_name), _memory_type);
992         return XCAM_RETURN_ERROR_MEM;
993     }
994     return XCAM_RETURN_NO_ERROR;
995 }
996 
997 XCamReturn
998 V4l2Device::init_buffer_pool ()
999 {
1000     XCamReturn ret = XCAM_RETURN_NO_ERROR;
1001     uint32_t i = 0;
1002 
1003     _buf_pool.clear ();
1004     _buf_pool.reserve (_buf_count);
1005 
1006     for (; i < _buf_count; i++) {
1007         SmartPtr<V4l2Buffer> new_buf;
1008         XCAM_LOG_DEBUG("allocate_buffer index: %d", i);
1009         ret = allocate_buffer (new_buf, _format, i);
1010         if (ret != XCAM_RETURN_NO_ERROR) {
1011             break;
1012         }
1013         _buf_pool.push_back (new_buf);
1014     }
1015 
1016     for (i = 0; i < _buf_count; i++) {
1017         SmartPtr<V4l2Buffer> &buf = _buf_pool [i];
1018         struct v4l2_buffer v4l2_buf = buf->get_buf ();
1019         XCAM_LOG_DEBUG ("init_buffer_pool device(%s) index:%d, memory:%d, type:%d, length:%d, fd:%d, ptr:%p",
1020                         XCAM_STR (_name), v4l2_buf.index, v4l2_buf.memory,
1021                         v4l2_buf.type, v4l2_buf.length, buf->get_expbuf_fd(), buf->get_expbuf_usrptr());
1022     }
1023     if (_buf_pool.empty()) {
1024         XCAM_LOG_ERROR ("No bufer allocated in device(%s)", XCAM_STR (_name));
1025         return XCAM_RETURN_ERROR_MEM;
1026     }
1027 
1028     if (i != _buf_count) {
1029         XCAM_LOG_WARNING (
1030             "device(%s) allocate buffer count:%d failback to %d",
1031             XCAM_STR (_name), _buf_count, i);
1032         _buf_count = i;
1033     }
1034 
1035     return XCAM_RETURN_NO_ERROR;
1036 }
1037 
1038 XCamReturn
1039 V4l2Device::fini_buffer_pool()
1040 {
1041     uint32_t i = 0;
1042     int32_t tried_time = 0;
1043 
1044     for (; i < _buf_pool.size(); i++) {
1045         release_buffer(_buf_pool [i]);
1046     }
1047 
1048     if (_memory_type == V4L2_MEMORY_MMAP) {
1049         struct v4l2_requestbuffers request_buf;
1050         xcam_mem_clear (request_buf);
1051         request_buf.type = _buf_type;
1052         request_buf.count = 0;
1053         request_buf.memory = _memory_type;
1054         do {
1055             if (io_control (VIDIOC_REQBUFS, &request_buf) < 0) {
1056                 usleep (100);
1057                 XCAM_LOG_ERROR ("device(%s) failed on VIDIOC_REQBUFS, retry %d < 50times", XCAM_STR (_name), tried_time);
1058                 //return XCAM_RETURN_ERROR_IOCTL;
1059             } else {
1060                 break;
1061             }
1062         } while(tried_time++ < 50);
1063     } else if (_memory_type == V4L2_MEMORY_DMABUF) {
1064         struct v4l2_requestbuffers request_buf;
1065         xcam_mem_clear (request_buf);
1066         request_buf.type = _buf_type;
1067         request_buf.count = 0;
1068         request_buf.memory = _memory_type;
1069         do {
1070             if (io_control (VIDIOC_REQBUFS, &request_buf) < 0) {
1071                 usleep (100);
1072                 XCAM_LOG_ERROR ("device(%s) failed on VIDIOC_REQBUFS, retry %d < 50times", XCAM_STR (_name), tried_time);
1073                 //return XCAM_RETURN_ERROR_IOCTL;
1074             } else {
1075                 break;
1076             }
1077         } while(tried_time++ < 50);
1078     }
1079 
1080     _buf_pool.clear ();
1081     if (_planes) {
1082         xcam_free (_planes);
1083         _planes = NULL;
1084     }
1085 
1086     return XCAM_RETURN_NO_ERROR;
1087 }
1088 
1089 SmartPtr<V4l2Buffer>
1090 V4l2Device::get_buffer_by_index (int index) {
1091     SmartLock auto_lock(_buf_mutex);
1092     SmartPtr<V4l2Buffer> &buf = _buf_pool [index];
1093 
1094     return buf;
1095 }
1096 
1097 XCamReturn
1098 V4l2Device::dequeue_buffer(SmartPtr<V4l2Buffer> &buf)
1099 {
1100     struct v4l2_buffer v4l2_buf;
1101     struct v4l2_plane planes[_mplanes_count];
1102 
1103     if (!is_activated()) {
1104         XCAM_LOG_DEBUG (
1105             "device(%s) dequeue buffer failed since not activated", XCAM_STR (_name));
1106         return XCAM_RETURN_ERROR_PARAM;
1107     }
1108 
1109     xcam_mem_clear (v4l2_buf);
1110     v4l2_buf.type = _buf_type;
1111     v4l2_buf.memory = _memory_type;
1112 
1113     if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
1114             V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
1115         memset(planes, 0, sizeof(struct v4l2_plane) * _mplanes_count);
1116         v4l2_buf.m.planes = planes;
1117         v4l2_buf.length = _mplanes_count;
1118     }
1119 
1120     if (_buf_sync)
1121         v4l2_buf.flags = V4L2_BUF_FLAG_NO_CACHE_INVALIDATE | V4L2_BUF_FLAG_NO_CACHE_CLEAN;
1122 
1123     if (this->io_control (VIDIOC_DQBUF, &v4l2_buf) < 0) {
1124         XCAM_LOG_ERROR ("device(%s) fail to dequeue buffer.", XCAM_STR (_name));
1125         return XCAM_RETURN_ERROR_IOCTL;
1126     }
1127 
1128     if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
1129             V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
1130         XCAM_LOG_DEBUG ("device(%s) multi planar dequeue buffer index:%d, length: %dn",
1131                         XCAM_STR (_name), v4l2_buf.index,
1132                         v4l2_buf.m.planes[0].length);
1133         if (V4L2_MEMORY_DMABUF == _memory_type) {
1134             XCAM_LOG_DEBUG ("device(%s) multi planar index:%d, fd: %d",
1135                             XCAM_STR (_name), v4l2_buf.index, v4l2_buf.m.planes[0].m.fd);
1136         }
1137     } else {
1138         XCAM_LOG_DEBUG ("device(%s) dequeue buffer index:%d, length: %d",
1139                         XCAM_STR (_name), v4l2_buf.index, v4l2_buf.length);
1140     }
1141 
1142     if (v4l2_buf.index > _buf_count) {
1143         XCAM_LOG_ERROR (
1144             "device(%s) dequeue wrong buffer index:%d",
1145             XCAM_STR (_name), v4l2_buf.index);
1146         return XCAM_RETURN_ERROR_ISP;
1147     }
1148 
1149     SmartLock auto_lock(_buf_mutex);
1150 
1151     buf = _buf_pool [v4l2_buf.index];
1152     buf->set_timestamp (v4l2_buf.timestamp);
1153     buf->set_timecode (v4l2_buf.timecode);
1154     buf->set_sequence (v4l2_buf.sequence);
1155     if (!V4L2_TYPE_IS_OUTPUT(_buf_type) &&
1156             (_buf_type != V4L2_BUF_TYPE_META_OUTPUT))
1157         buf->set_queued(false);
1158     if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
1159             V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
1160         buf->set_length (v4l2_buf.m.planes[0].length);
1161     } else {
1162         buf->set_length (v4l2_buf.length);
1163     }
1164     _queued_bufcnt--;
1165 
1166     return XCAM_RETURN_NO_ERROR;
1167 }
1168 
1169 XCamReturn
1170 V4l2Device::get_buffer (SmartPtr<V4l2Buffer> &buf, int index) const
1171 {
1172     SmartLock auto_lock(_buf_mutex);
1173 
1174     if (_buf_pool.size() <= 0)
1175         return XCAM_RETURN_ERROR_MEM;
1176 
1177     if (index != -1 && !(_buf_pool[index]->get_queued())) {
1178         buf = _buf_pool[index];
1179         buf->set_queued(true);
1180         return XCAM_RETURN_NO_ERROR;
1181     }
1182 
1183     uint32_t i;
1184 
1185     for (i = 0; i < _buf_pool.size(); i++) {
1186         if (!(_buf_pool[i]->get_queued())) {
1187             buf = _buf_pool[i];
1188             buf->set_queued(true);
1189             break;
1190         }
1191     }
1192 
1193     if (i == _buf_count)
1194         return XCAM_RETURN_ERROR_MEM;
1195     else
1196         return XCAM_RETURN_NO_ERROR;
1197 }
1198 
1199 XCamReturn
1200 V4l2Device::return_buffer_to_pool (SmartPtr<V4l2Buffer> &buf)
1201 {
1202     SmartLock auto_lock(_buf_mutex);
1203 
1204     XCAM_ASSERT (buf.ptr());
1205     buf->reset ();
1206     return XCAM_RETURN_NO_ERROR;
1207 }
1208 
1209 XCamReturn
1210 V4l2Device::return_buffer (SmartPtr<V4l2Buffer> &buf)
1211 {
1212     SmartLock auto_lock(_buf_mutex);
1213 
1214    if (V4L2_TYPE_IS_OUTPUT(buf->get_buf ().type) ||
1215             (buf->get_buf ().type == V4L2_BUF_TYPE_META_OUTPUT)) {
1216         XCAM_ASSERT (buf.ptr());
1217         buf->reset ();
1218         return XCAM_RETURN_NO_ERROR;
1219    } else {
1220         if (!_active)
1221             buf->reset();
1222         else
1223             return queue_buffer (buf, true);
1224    }
1225 
1226    return XCAM_RETURN_NO_ERROR;
1227 }
1228 
1229 XCamReturn
1230 V4l2Device::queue_buffer (SmartPtr<V4l2Buffer> &buf, bool locked)
1231 {
1232     if (!locked)
1233         _buf_mutex.lock();
1234 
1235     XCAM_ASSERT (buf.ptr());
1236     buf->reset ();
1237 
1238     struct v4l2_buffer v4l2_buf = buf->get_buf ();
1239     struct v4l2_plane planes[_mplanes_count];
1240 
1241     XCAM_ASSERT (v4l2_buf.index < _buf_count);
1242 
1243     if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == _buf_type ||
1244             V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == _buf_type) {
1245         XCAM_LOG_DEBUG ("device(%s) queue buffer index:%d, memory:%d, type:%d, multiply planar:%d, length:%d, fd:%d, ptr:%p",
1246                         XCAM_STR (_name), v4l2_buf.index, v4l2_buf.memory,
1247                         v4l2_buf.type, v4l2_buf.length, v4l2_buf.m.planes[0].length, buf->get_expbuf_fd(), buf->get_expbuf_usrptr());
1248         memset(planes, 0, sizeof(struct v4l2_plane) * _mplanes_count);
1249         v4l2_buf.m.planes = planes;
1250         planes[0] = buf->get_buf ().m.planes[0];
1251     } else {
1252         XCAM_LOG_DEBUG ("device(%s) queue buffer index:%d, memory:%d, type:%d, length:%d, fd:%d",
1253                         XCAM_STR (_name), v4l2_buf.index, v4l2_buf.memory,
1254                         v4l2_buf.type, v4l2_buf.length, buf->get_expbuf_fd());
1255     }
1256 
1257     if (v4l2_buf.type == V4L2_BUF_TYPE_META_OUTPUT)
1258         v4l2_buf.bytesused = v4l2_buf.length;
1259     if (v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1260         v4l2_buf.m.planes[0].bytesused = v4l2_buf.m.planes[0].length;
1261         if (V4L2_MEMORY_DMABUF == _memory_type)
1262             v4l2_buf.m.planes[0].m.fd = buf->get_expbuf_fd();
1263         else if (V4L2_MEMORY_USERPTR == _memory_type)
1264             v4l2_buf.m.planes[0].m.userptr = buf->get_expbuf_usrptr();
1265     }
1266 
1267     _queued_bufcnt++;
1268     buf->set_queued(true);
1269     if (!locked)
1270         _buf_mutex.unlock();
1271 
1272     if (_buf_sync)
1273         v4l2_buf.flags = V4L2_BUF_FLAG_NO_CACHE_INVALIDATE | V4L2_BUF_FLAG_NO_CACHE_CLEAN;
1274 
1275     if (io_control (VIDIOC_QBUF, &v4l2_buf) < 0) {
1276         XCAM_LOG_ERROR("%s fail to enqueue buffer index:%d.",
1277                        XCAM_STR(_name), v4l2_buf.index);
1278         // restore buf status
1279         {
1280             if (!locked)
1281                 _buf_mutex.lock();
1282             /* SmartLock auto_lock(_buf_mutex); */
1283             buf->set_queued(false);
1284             _queued_bufcnt--;
1285             if (!locked)
1286                 _buf_mutex.unlock();
1287         }
1288 
1289         return XCAM_RETURN_ERROR_IOCTL;
1290     }
1291 
1292     return XCAM_RETURN_NO_ERROR;
1293 }
1294 
1295 V4l2SubDevice::V4l2SubDevice (const char *name)
1296     : V4l2Device (name)
1297 {
1298 }
1299 
1300 XCamReturn
1301 V4l2Device::subscribe_event (int event)
1302 {
1303     struct v4l2_event_subscription sub;
1304     int ret = 0;
1305 
1306     XCAM_ASSERT (is_opened());
1307 
1308     xcam_mem_clear (sub);
1309     sub.type = event;
1310 
1311     ret = this->io_control (VIDIOC_SUBSCRIBE_EVENT, &sub);
1312     if (ret < 0) {
1313         XCAM_LOG_DEBUG ("subdev(%s) subscribe event(%d) failed", XCAM_STR(_name), event);
1314         return XCAM_RETURN_ERROR_IOCTL;
1315     }
1316     return XCAM_RETURN_NO_ERROR;
1317 }
1318 
1319 XCamReturn
1320 V4l2Device::unsubscribe_event (int event)
1321 {
1322     struct v4l2_event_subscription sub;
1323     int ret = 0;
1324 
1325     XCAM_ASSERT (is_opened());
1326 
1327     xcam_mem_clear (sub);
1328     sub.type = event;
1329 
1330     ret = this->io_control (VIDIOC_UNSUBSCRIBE_EVENT, &sub);
1331     if (ret < 0) {
1332         XCAM_LOG_DEBUG ("subdev(%s) unsubscribe event(%d) failed", XCAM_STR(_name), event);
1333         return XCAM_RETURN_ERROR_IOCTL;
1334     }
1335     return XCAM_RETURN_NO_ERROR;
1336 }
1337 
1338 XCamReturn
1339 V4l2Device::dequeue_event (struct v4l2_event &event)
1340 {
1341     int ret = 0;
1342     XCAM_ASSERT (is_opened());
1343 
1344     ret = this->io_control (VIDIOC_DQEVENT, &event);
1345     if (ret < 0) {
1346         XCAM_LOG_DEBUG ("subdev(%s) dequeue event failed", XCAM_STR(_name));
1347         return XCAM_RETURN_ERROR_IOCTL;
1348     }
1349 
1350     return XCAM_RETURN_NO_ERROR;
1351 }
1352 
1353 XCamReturn
1354 V4l2SubDevice::get_selection (int pad, uint32_t target, struct v4l2_subdev_selection &select)
1355 {
1356     int ret = 0;
1357     XCAM_ASSERT (is_opened());
1358 
1359     select.pad = pad;
1360     select.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1361     select.target = target;
1362 
1363     ret = this->io_control (VIDIOC_SUBDEV_G_SELECTION, &select);
1364     if (ret < 0) {
1365         XCAM_LOG_DEBUG ("subdev(%s) get selection failed", XCAM_STR(_name));
1366         return XCAM_RETURN_ERROR_IOCTL;
1367     }
1368 
1369     return XCAM_RETURN_NO_ERROR;
1370 }
1371 
1372 XCamReturn V4l2SubDevice::start (bool prepared)
1373 {
1374     if (!is_opened())
1375         return XCAM_RETURN_ERROR_PARAM;
1376 
1377     _active = true;
1378     return XCAM_RETURN_NO_ERROR;
1379 }
1380 
1381 XCamReturn V4l2SubDevice::stop ()
1382 {
1383     if (_active)
1384         _active = false;
1385 
1386     return XCAM_RETURN_NO_ERROR;
1387 }
1388 
1389 }
1390