From 9e206c9ed5bcbf4fb169bfa55ac6fa5db992fab9 Mon Sep 17 00:00:00 2001 From: shizhenghui Date: Thu, 7 Dec 2023 16:28:02 +0800 Subject: [PATCH] Refactor nuttx v4l2 Adjust the v4l2 framework to support both capture and v4l2m2m, and can easily add other v4l2 features. Signed-off-by: shizhenghui --- boards/sim/sim/sim/src/sim_bringup.c | 6 +- drivers/video/CMakeLists.txt | 2 +- drivers/video/Make.defs | 2 +- drivers/video/goldfish_camera.c | 6 +- drivers/video/{video.c => v4l2_cap.c} | 4485 +++++++++++++------------ drivers/video/v4l2_core.c | 533 +++ include/nuttx/video/v4l2_cap.h | 87 + include/nuttx/video/video.h | 110 +- 8 files changed, 2986 insertions(+), 2245 deletions(-) rename drivers/video/{video.c => v4l2_cap.c} (52%) create mode 100644 drivers/video/v4l2_core.c create mode 100644 include/nuttx/video/v4l2_cap.h diff --git a/boards/sim/sim/sim/src/sim_bringup.c b/boards/sim/sim/sim/src/sim_bringup.c index 88481eaa4ca57..5bfd71ddd944b 100644 --- a/boards/sim/sim/sim/src/sim_bringup.c +++ b/boards/sim/sim/sim/src/sim_bringup.c @@ -47,7 +47,7 @@ #include #include #include -#include +#include #include #include #include @@ -300,10 +300,10 @@ int sim_bringup(void) sim_camera_initialize(); - ret = video_initialize(CONFIG_SIM_CAMERA_DEV_PATH); + ret = capture_initialize(CONFIG_SIM_CAMERA_DEV_PATH); if (ret < 0) { - syslog(LOG_ERR, "ERROR: video_initialize() failed: %d\n", ret); + syslog(LOG_ERR, "ERROR: capture_initialize() failed: %d\n", ret); } #endif diff --git a/drivers/video/CMakeLists.txt b/drivers/video/CMakeLists.txt index 3462ba26e2fe7..d1db060dfa80f 100644 --- a/drivers/video/CMakeLists.txt +++ b/drivers/video/CMakeLists.txt @@ -29,7 +29,7 @@ if(CONFIG_DRIVERS_VIDEO) endif() if(CONFIG_VIDEO_STREAM) - list(APPEND SRCS video.c video_framebuff.c) + list(APPEND SRCS v4l2_core.c video_framebuff.c v4l2_cap.c) endif() # These video drivers depend on I2C support diff --git a/drivers/video/Make.defs b/drivers/video/Make.defs index 3bd614f612daa..2ba0082996c10 100644 --- a/drivers/video/Make.defs +++ b/drivers/video/Make.defs @@ -27,7 +27,7 @@ ifeq ($(CONFIG_VIDEO_FB),y) endif ifeq ($(CONFIG_VIDEO_STREAM),y) - CSRCS += video.c video_framebuff.c + CSRCS += v4l2_core.c video_framebuff.c v4l2_cap.c endif # These video drivers depend on I2C support diff --git a/drivers/video/goldfish_camera.c b/drivers/video/goldfish_camera.c index a397b6e996b51..8984f46ecced3 100644 --- a/drivers/video/goldfish_camera.c +++ b/drivers/video/goldfish_camera.c @@ -34,6 +34,7 @@ #include #include #include +#include /**************************************************************************** * Pre-processor Definitions @@ -779,10 +780,7 @@ int goldfish_camera_initialize(void) snprintf(devpath, sizeof(devpath), "/dev/video%zd", i); } - video_register(devpath, - &priv[i]->data, - &sensor, - 1); + capture_register(devpath, &priv[i]->data, &sensor, 1); } return 0; diff --git a/drivers/video/video.c b/drivers/video/v4l2_cap.c similarity index 52% rename from drivers/video/video.c rename to drivers/video/v4l2_cap.c index 1acbb10212b8f..c104f08718f5e 100644 --- a/drivers/video/video.c +++ b/drivers/video/v4l2_cap.c @@ -1,5 +1,5 @@ /**************************************************************************** - * drivers/video/video.c + * drivers/video/v4l2_cap.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -22,23 +22,16 @@ * Included Files ****************************************************************************/ -#include - #include #include -#include -#include #include #include #include #include -#include #include - +#include #include -#include -#include #include "video_framebuff.h" @@ -46,84 +39,74 @@ * Pre-processor Definitions ****************************************************************************/ -#define MAX_VIDEO_FILE_PATH (32) -#define MAX_VIDEO_FMT (2) -#define VIDEO_FMT_MAIN (0) -#define VIDEO_FMT_SUB (1) +#define MAX_CAPTURE_FMT (2) +#define CAPTURE_FMT_MAIN (0) +#define CAPTURE_FMT_SUB (1) -#define VIDEO_REMAINING_CAPNUM_INFINITY (-1) +#define REMAINING_CAPNUM_INFINITY (-1) -#define VIDEO_ID(x, y) (((x) << 16) | (y)) +#define CAPTURE_ID(x, y) (((x) << 16) | (y)) /**************************************************************************** * Private Types ****************************************************************************/ -enum video_state_e +enum capture_state_e { - VIDEO_STATE_STREAMOFF = 0, /* Capture trigger event is not received */ - VIDEO_STATE_STREAMON = 1, /* Capture trigger event is received, - * but capture is not operated. - */ - VIDEO_STATE_CAPTURE = 2, /* On capture */ + CAPTURE_STATE_STREAMOFF = 0, /* Capture trigger event is not received */ + CAPTURE_STATE_STREAMON = 1, /* Capture trigger event is received, + * but capture is not operated. + */ + CAPTURE_STATE_CAPTURE = 2, /* On capture */ }; -enum video_state_transition_cause +enum capture_state_cause_e { - CAUSE_VIDEO_STOP = 0, /* Stop capture event for video stream */ - CAUSE_VIDEO_START = 1, /* Start capture event for video stream */ - CAUSE_VIDEO_DQBUF = 2, /* DQBUF timing for video stream */ - CAUSE_STILL_STOP = 3, /* Stop capture event for still stream */ - CAUSE_STILL_START = 4, /* Start capture event for still stream */ + CAUSE_CAPTURE_STOP = 0, /* Stop capture event for capture stream */ + CAUSE_CAPTURE_START = 1, /* Start capture event for capture stream */ + CAUSE_CAPTURE_DQBUF = 2, /* DQBUF timing for video stream */ + CAUSE_STILL_STOP = 3, /* Stop capture event for still stream */ + CAUSE_STILL_START = 4, /* Start capture event for still stream */ }; -enum video_waitend_cause_e +enum capture_waitend_cause_e { - VIDEO_WAITEND_CAUSE_CAPTUREDONE = 0, - VIDEO_WAITEND_CAUSE_DQCANCEL = 1, - VIDEO_WAITEND_CAUSE_STILLSTOP = 2, + WAITEND_CAUSE_CAPTUREDONE = 0, + WAITEND_CAUSE_DQCANCEL = 1, + WAITEND_CAUSE_STILLSTOP = 2, }; -struct video_wait_capture_s +struct capture_wait_capture_s { sem_t dqbuf_wait_flg; /* Save container which capture is done */ FAR vbuf_container_t *done_container; - enum video_waitend_cause_e waitend_cause; -}; - -typedef struct video_wait_capture_s video_wait_capture_t; - -struct video_format_s -{ - uint16_t width; - uint16_t height; - uint32_t pixelformat; + enum capture_waitend_cause_e waitend_cause; }; -typedef struct video_format_s video_format_t; - -struct video_type_inf_s -{ - mutex_t lock_state; - enum video_state_e state; - int32_t remaining_capnum; - video_wait_capture_t wait_capture; - uint8_t nr_fmt; - video_format_t fmt[MAX_VIDEO_FMT]; - struct v4l2_rect clip; - struct v4l2_fract frame_interval; - video_framebuff_t bufinf; - FAR uint8_t *bufheap; /* for V4L2_MEMORY_MMAP buffers */ - FAR struct pollfd *fds; - uint32_t seqnum; +typedef struct capture_wait_capture_s capture_wait_capture_t; + +struct capture_type_inf_s +{ + mutex_t lock_state; + enum capture_state_e state; + int32_t remaining_capnum; + capture_wait_capture_t wait_capture; + uint8_t nr_fmt; + video_format_t fmt[MAX_CAPTURE_FMT]; + struct v4l2_rect clip; + struct v4l2_fract frame_interval; + video_framebuff_t bufinf; + FAR uint8_t *bufheap; /* for V4L2_MEMORY_MMAP buffers */ + FAR struct pollfd *fds; + uint32_t seqnum; }; -typedef struct video_type_inf_s video_type_inf_t; +typedef struct capture_type_inf_s capture_type_inf_t; -struct video_scene_params_s +struct capture_scene_params_s { uint8_t mode; /* enum v4l2_scene_mode */ @@ -164,78 +147,61 @@ struct video_scene_params_s int32_t jpeg_quality; }; -typedef struct video_scene_params_s video_scene_params_t; +typedef struct capture_scene_params_s capture_scene_params_t; -struct video_parameter_name_s +struct capture_parameter_name_s { uint32_t id; const char *name; }; -typedef struct video_parameter_name_s video_parameter_name_t; +typedef struct capture_parameter_name_s capture_parameter_name_t; -struct video_mng_s +struct capture_mng_s { - /* Parameter of video_initialize() */ + struct v4l2_s v4l2; - FAR char *devpath; - mutex_t lock_open_num; - uint8_t open_num; - video_type_inf_t video_inf; - video_type_inf_t still_inf; - FAR struct imgdata_s *imgdata; - FAR struct imgsensor_s *imgsensor; - enum v4l2_scene_mode video_scene_mode; - uint8_t video_scence_num; - FAR video_scene_params_t *video_scene_param[V4L2_SCENE_MODE_MAX]; + /* Parameter of capture_initialize() */ + + mutex_t lock_open_num; + uint8_t open_num; + capture_type_inf_t capture_inf; + capture_type_inf_t still_inf; + FAR struct imgdata_s *imgdata; + FAR struct imgsensor_s *imgsensor; + enum v4l2_scene_mode capture_scene_mode; + uint8_t capture_scence_num; + FAR capture_scene_params_t *capture_scene_param[V4L2_SCENE_MODE_MAX]; #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS - bool unlinked; + bool unlinked; #endif }; -typedef struct video_mng_s video_mng_t; +typedef struct capture_mng_s capture_mng_t; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -/* Character driver methods. */ - -static int video_open(FAR struct file *filep); -static int video_close(FAR struct file *filep); -static ssize_t video_read(FAR struct file *filep, - FAR char *buffer, size_t buflen); -static ssize_t video_write(FAR struct file *filep, - FAR const char *buffer, size_t buflen); -static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg); -static int video_mmap(FAR struct file *filep, - FAR struct mm_map_entry_s *map); -static int video_poll(FAR struct file *filep, FAR struct pollfd *fds, - bool setup); -#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS -static int video_unlink(FAR struct inode *inode); -#endif -/* Common function */ - -static FAR video_type_inf_t * -get_video_type_inf(FAR video_mng_t *vmng, uint8_t type); -static enum video_state_e -estimate_next_video_state(FAR video_mng_t *vmng, - enum video_state_transition_cause cause); -static void change_video_state(FAR video_mng_t *vmng, - enum video_state_e next_state); -static bool is_taking_still_picture(FAR video_mng_t *vmng); -static bool is_bufsize_sufficient(FAR video_mng_t *vmng, uint32_t bufsize); -static void cleanup_resources(FAR video_mng_t *vmng); +static FAR capture_type_inf_t * +get_capture_type_inf(FAR capture_mng_t *cmng, uint8_t type); +static enum capture_state_e +estimate_next_capture_state(FAR capture_mng_t *cmng, + enum capture_state_cause_e cause); +static void change_capture_state(FAR capture_mng_t *cmng, + enum capture_state_e next_state); +static bool is_taking_still_picture(FAR capture_mng_t *cmng); +static bool is_bufsize_sufficient(FAR capture_mng_t *cmng, uint32_t bufsize); +static void cleanup_resources(FAR capture_mng_t *cmng); static bool is_sem_waited(FAR sem_t *sem); -static int save_scene_param(FAR video_mng_t *vmng, +static int save_scene_param(FAR capture_mng_t *cmng, enum v4l2_scene_mode mode, uint32_t id, struct v4l2_ext_control *control); -static int video_complete_capture(uint8_t err_code, uint32_t datasize, - FAR const struct timeval *ts, - FAR void *arg); -static int validate_frame_setting(FAR video_mng_t *vmng, +static int complete_capture(uint8_t err_code, uint32_t datasize, + FAR const struct timeval *ts, + FAR void *arg); +static int validate_frame_setting(FAR capture_mng_t *cmng, enum v4l2_buf_type type, uint8_t nr_fmt, FAR video_format_t *vfmt, @@ -243,153 +209,342 @@ static int validate_frame_setting(FAR video_mng_t *vmng, FAR struct v4l2_fract *interval); static size_t get_bufsize(FAR video_format_t *vf); -/* Internal function for each cmds of ioctl */ - -static int video_querycap(FAR video_mng_t *vmng, - FAR struct v4l2_capability *cap); -static int video_g_input(FAR int *num); -static int video_enum_input(FAR video_mng_t *vmng, - FAR struct v4l2_input *input); -static int video_reqbufs(FAR struct video_mng_s *vmng, - FAR struct v4l2_requestbuffers *reqbufs); -static int video_qbuf(FAR struct video_mng_s *vmng, - FAR struct v4l2_buffer *buf); -static int video_dqbuf(FAR struct video_mng_s *vmng, - FAR struct v4l2_buffer *buf, - int oflags); -static int video_cancel_dqbuf(FAR struct video_mng_s *vmng, - enum v4l2_buf_type type); -static int video_g_fmt(FAR struct video_mng_s *priv, - FAR struct v4l2_format *fmt); -static int video_s_fmt(FAR struct video_mng_s *priv, - FAR struct v4l2_format *fmt); -static int video_try_fmt(FAR struct video_mng_s *priv, - FAR struct v4l2_format *v4l2); -static int video_g_parm(FAR struct video_mng_s *priv, - FAR struct v4l2_streamparm *parm); -static int video_s_parm(FAR struct video_mng_s *priv, - FAR struct v4l2_streamparm *parm); -static int video_streamon(FAR struct video_mng_s *vmng, - FAR enum v4l2_buf_type *type); -static int video_streamoff(FAR struct video_mng_s *vmng, - FAR enum v4l2_buf_type *type); -static int video_do_halfpush(FAR struct video_mng_s *priv, - bool enable); -static int video_takepict_start(FAR struct video_mng_s *vmng, - int32_t capture_num); -static int video_takepict_stop(FAR struct video_mng_s *vmng, - bool halfpush); -static int video_queryctrl(FAR video_mng_t *vmng, - FAR struct v4l2_queryctrl *ctrl); -static int video_query_ext_ctrl(FAR video_mng_t *vmng, - FAR struct v4l2_query_ext_ctrl *ctrl); -static int video_querymenu(FAR video_mng_t *vmng, - FAR struct v4l2_querymenu *menu); -static int video_g_ctrl(FAR struct video_mng_s *priv, - FAR struct v4l2_control *ctrl); -static int video_s_ctrl(FAR struct video_mng_s *priv, - FAR struct v4l2_control *ctrl); -static int video_g_ext_ctrls(FAR struct video_mng_s *priv, - FAR struct v4l2_ext_controls *ctrls); -static int video_s_ext_ctrls(FAR struct video_mng_s *priv, - FAR struct v4l2_ext_controls *ctrls); -static int video_query_ext_ctrl_scene(FAR video_mng_t *vmng, - FAR struct v4s_query_ext_ctrl_scene *ctrl); -static int video_querymenu_scene(FAR video_mng_t *vmng, - FAR struct v4s_querymenu_scene *menu); -static int video_g_ext_ctrls_scene(FAR video_mng_t *vmng, - FAR struct v4s_ext_controls_scene *ctrls); -static int video_s_ext_ctrls_scene(FAR video_mng_t *vmng, - FAR struct v4s_ext_controls_scene *ctrls); +/* ioctl function for each cmds of ioctl */ + +static int capture_querycap(FAR struct v4l2_s *v4l2, + FAR struct v4l2_capability *cap); +static int capture_g_input(FAR int *num); +static int capture_enum_input(FAR struct v4l2_s *v4l2, + FAR struct v4l2_input *input); +static int capture_reqbufs(FAR struct v4l2_s *v4l2, + FAR struct v4l2_requestbuffers *reqbufs); +static int capture_querybuf(FAR struct v4l2_s *v4l2, + FAR struct v4l2_buffer *buf); +static int capture_qbuf(FAR struct v4l2_s *v4l2, + FAR struct v4l2_buffer *buf); +static int capture_dqbuf(FAR struct v4l2_s *v4l2, + FAR struct v4l2_buffer *buf, int oflags); +static int capture_cancel_dqbuf(FAR struct v4l2_s *v4l2, + enum v4l2_buf_type type); +static int capture_g_fmt(FAR struct v4l2_s *v4l2, + FAR struct v4l2_format *fmt); +static int capture_s_fmt(FAR struct v4l2_s *v4l2, + FAR struct v4l2_format *fmt); +static int capture_try_fmt(FAR struct v4l2_s *v4l2, + FAR struct v4l2_format *fmt); +static int capture_g_parm(FAR struct v4l2_s *v4l2, + FAR struct v4l2_streamparm *parm); +static int capture_s_parm(FAR struct v4l2_s *v4l2, + FAR struct v4l2_streamparm *parm); +static int capture_streamon(FAR struct v4l2_s *v4l2, + FAR enum v4l2_buf_type *type); +static int capture_streamoff(FAR struct v4l2_s *v4l2, + FAR enum v4l2_buf_type *type); +static int capture_do_halfpush(FAR struct v4l2_s *v4l2, + bool enable); +static int capture_takepict_start(FAR struct v4l2_s *v4l2, + int32_t capture_num); +static int capture_takepict_stop(FAR struct v4l2_s *v4l2, + bool halfpush); +static int capture_s_selection(FAR struct v4l2_s *v4l2, + FAR struct v4l2_selection *clip); +static int capture_g_selection(FAR struct v4l2_s *v4l2, + FAR struct v4l2_selection *clip); +static int capture_queryctrl(FAR struct v4l2_s *v4l2, + FAR struct v4l2_queryctrl *ctrl); +static int capture_query_ext_ctrl(FAR struct v4l2_s *v4l2, + FAR struct v4l2_query_ext_ctrl *ctrl); +static int capture_querymenu(FAR struct v4l2_s *v4l2, + FAR struct v4l2_querymenu *menu); +static int capture_g_ctrl(FAR struct v4l2_s *v4l2, + FAR struct v4l2_control *ctrl); +static int capture_s_ctrl(FAR struct v4l2_s *v4l2, + FAR struct v4l2_control *ctrl); +static int capture_g_ext_ctrls(FAR struct v4l2_s *v4l2, + FAR struct v4l2_ext_controls *ctrls); +static int capture_s_ext_ctrls(FAR struct v4l2_s *v4l2, + FAR struct v4l2_ext_controls *ctrls); +static int capture_query_ext_ctrl_scene(FAR struct v4l2_s *v4l2, + FAR struct v4s_query_ext_ctrl_scene *ctrl); +static int capture_querymenu_scene(FAR struct v4l2_s *v4l2, + FAR struct v4s_querymenu_scene *menu); +static int capture_g_ext_ctrls_scene(FAR struct v4l2_s *v4l2, + FAR struct v4s_ext_controls_scene *ctrls); +static int capture_s_ext_ctrls_scene(FAR struct v4l2_s *v4l2, + FAR struct v4s_ext_controls_scene *ctrls); +static int capture_enum_fmt(FAR struct v4l2_s *v4l2, + FAR struct v4l2_fmtdesc *f); +static int capture_enum_frminterval(FAR struct v4l2_s *v4l2, + FAR struct v4l2_frmivalenum *f); +static int capture_enum_frmsize(FAR struct v4l2_s *v4l2, + FAR struct v4l2_frmsizeenum *f); + +/* File operations function */ + +static int capture_open(FAR struct file *filep); +static int capture_close(FAR struct file *filep); +static int capture_mmap(FAR struct file *filep, + FAR struct mm_map_entry_s *map); +static int capture_poll(FAR struct file *filep, + FAR struct pollfd *fds, bool setup); +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int capture_unlink(FAR struct inode *inode); +#endif /**************************************************************************** * Private Data ****************************************************************************/ -static const struct file_operations g_video_fops = -{ - video_open, /* open */ - video_close, /* close */ - video_read, /* read */ - video_write, /* write */ - NULL, /* seek */ - video_ioctl, /* ioctl */ - video_mmap, /* mmap */ - NULL, /* truncate */ - video_poll, /* poll */ +static const struct v4l2_ops_s g_capture_vops = +{ + capture_querycap, /* querycap */ + capture_g_input, /* g_input */ + capture_enum_input, /* enum_input */ + capture_reqbufs, /* reqbufs */ + capture_querybuf, /* querybuf */ + capture_qbuf, /* qbuf */ + capture_dqbuf, /* dqbuf */ + capture_cancel_dqbuf, /* cancel_dqbuf */ + capture_g_fmt, /* g_fmt */ + capture_s_fmt, /* s_fmt */ + capture_try_fmt, /* try_fmt */ + capture_g_parm, /* g_parm */ + capture_s_parm, /* s_parm */ + capture_streamon, /* streamon */ + capture_streamoff, /* streamoff */ + capture_do_halfpush, /* do_halfpush */ + capture_takepict_start, /* takepict_start */ + capture_takepict_stop, /* takepict_stop */ + capture_s_selection, /* s_selection */ + capture_g_selection, /* g_selection */ + capture_queryctrl, /* queryctrl */ + capture_query_ext_ctrl, /* query_ext_ctrl */ + capture_querymenu, /* querymenu */ + capture_g_ctrl, /* g_ctrl */ + capture_s_ctrl, /* s_ctrl */ + capture_g_ext_ctrls, /* g_ext_ctrls */ + capture_s_ext_ctrls, /* s_ext_ctrls */ + capture_query_ext_ctrl_scene, /* query_ext_ctrl_scene */ + capture_querymenu_scene, /* querymenu_scene */ + capture_g_ext_ctrls_scene, /* g_ext_ctrls_scene */ + capture_s_ext_ctrls_scene, /* s_ext_ctrls_scene */ + capture_enum_fmt, /* enum_fmt */ + capture_enum_frminterval, /* enum_frminterval */ + capture_enum_frmsize /* enum_frmsize */ +}; + +static const struct file_operations g_capture_fops = +{ + capture_open, /* open */ + capture_close, /* close */ + NULL, /* read */ + NULL, /* write */ + NULL, /* seek */ + NULL, /* ioctl */ + capture_mmap, /* mmap */ + NULL, /* truncate */ + capture_poll, /* poll */ #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS - video_unlink, /* unlink */ + capture_unlink, /* unlink */ #endif }; -static const video_parameter_name_t g_video_parameter_name[] = -{ - {IMGSENSOR_ID_BRIGHTNESS, "Brightness"}, - {IMGSENSOR_ID_CONTRAST, "Contrast"}, - {IMGSENSOR_ID_SATURATION, "Saturation"}, - {IMGSENSOR_ID_HUE, "Hue"}, - {IMGSENSOR_ID_AUTO_WHITE_BALANCE, "Automatic white balance"}, - {IMGSENSOR_ID_RED_BALANCE, "Red balance"}, - {IMGSENSOR_ID_BLUE_BALANCE, "Blue balance"}, - {IMGSENSOR_ID_GAMMA, "Gamma value"}, - {IMGSENSOR_ID_GAMMA_CURVE, "Gamma adjustment(curve)"}, - {IMGSENSOR_ID_EXPOSURE, "Exposure value"}, - {IMGSENSOR_ID_HFLIP_VIDEO, "Mirror horizontally(VIDEO)"}, - {IMGSENSOR_ID_VFLIP_VIDEO, "Mirror vertically(VIDEO)"}, - {IMGSENSOR_ID_HFLIP_STILL, "Mirror horizontally(STILL)"}, - {IMGSENSOR_ID_VFLIP_STILL, "Mirror vertically(STILL)"}, - {IMGSENSOR_ID_SHARPNESS, "Sharpness"}, - {IMGSENSOR_ID_COLOR_KILLER, "Color killer"}, - {IMGSENSOR_ID_COLORFX, "Color effect"}, - {IMGSENSOR_ID_AUTOBRIGHTNESS, "Auto brightness"}, - {IMGSENSOR_ID_ROTATE, "Rotate"}, - {IMGSENSOR_ID_EXPOSURE_AUTO, "Auto Exposure"}, - {IMGSENSOR_ID_EXPOSURE_ABSOLUTE, "Exposure time(100 usec)"}, - {IMGSENSOR_ID_FOCUS_ABSOLUTE, "Focus(absolute value)"}, - {IMGSENSOR_ID_FOCUS_RELATIVE, "Focus(relative value)"}, - {IMGSENSOR_ID_FOCUS_AUTO, "Continuous Auto Focus"}, - {IMGSENSOR_ID_ZOOM_ABSOLUTE, "Zoom(absolute value)"}, - {IMGSENSOR_ID_ZOOM_RELATIVE, "Zoom(relative value)"}, - {IMGSENSOR_ID_ZOOM_CONTINUOUS, "Continuous zoom"}, - {IMGSENSOR_ID_IRIS_ABSOLUTE, "Iris(absolute value)"}, - {IMGSENSOR_ID_IRIS_RELATIVE, "Iris(relative value)"}, - {IMGSENSOR_ID_AUTO_N_PRESET_WB, "Preset white balance"}, - {IMGSENSOR_ID_WIDE_DYNAMIC_RANGE, "Wide dynamic range"}, - {IMGSENSOR_ID_IMG_STABILIZATION, "Image stabilization"}, - {IMGSENSOR_ID_ISO_SENSITIVITY, "ISO sensitivity"}, - {IMGSENSOR_ID_ISO_SENSITIVITY_AUTO, "Automatic ISO sensitivity"}, - {IMGSENSOR_ID_EXPOSURE_METERING, "Photometry"}, - {IMGSENSOR_ID_SPOT_POSITION, "Spot position"}, - {IMGSENSOR_ID_3A_LOCK, "Lock AWB/AE"}, - {IMGSENSOR_ID_AUTO_FOCUS_START, "Start single Auto Focus"}, - {IMGSENSOR_ID_AUTO_FOCUS_STOP, "Stop single Auto Focus"}, - {IMGSENSOR_ID_3A_PARAMETER, "3A parameter"}, - {IMGSENSOR_ID_3A_STATUS, "3A status"}, - {IMGSENSOR_ID_FLASH_LED_MODE, "LED mode"}, - {IMGSENSOR_ID_JPEG_QUALITY, "JPEG compression quality"} +static const capture_parameter_name_t g_capture_parameter_name[] = +{ + { + IMGSENSOR_ID_BRIGHTNESS, "Brightness" + }, + + { + IMGSENSOR_ID_CONTRAST, "Contrast" + }, + + { + IMGSENSOR_ID_SATURATION, "Saturation" + }, + + { + IMGSENSOR_ID_HUE, "Hue" + }, + + { + IMGSENSOR_ID_AUTO_WHITE_BALANCE, "Automatic white balance" + }, + + { + IMGSENSOR_ID_RED_BALANCE, "Red balance" + }, + + { + IMGSENSOR_ID_BLUE_BALANCE, "Blue balance" + }, + + { + IMGSENSOR_ID_GAMMA, "Gamma value" + }, + + { + IMGSENSOR_ID_GAMMA_CURVE, "Gamma adjustment(curve)" + }, + + { + IMGSENSOR_ID_EXPOSURE, "Exposure value" + }, + + { + IMGSENSOR_ID_HFLIP_VIDEO, "Mirror horizontally(VIDEO)" + }, + + { + IMGSENSOR_ID_VFLIP_VIDEO, "Mirror vertically(VIDEO)" + }, + + { + IMGSENSOR_ID_HFLIP_STILL, "Mirror horizontally(STILL)" + }, + + { + IMGSENSOR_ID_VFLIP_STILL, "Mirror vertically(STILL)" + }, + + { + IMGSENSOR_ID_SHARPNESS, "Sharpness" + }, + + { + IMGSENSOR_ID_COLOR_KILLER, "Color killer" + }, + + { + IMGSENSOR_ID_COLORFX, "Color effect" + }, + + { + IMGSENSOR_ID_AUTOBRIGHTNESS, "Auto brightness" + }, + + { + IMGSENSOR_ID_ROTATE, "Rotate" + }, + + { + IMGSENSOR_ID_EXPOSURE_AUTO, "Auto Exposure" + }, + + { + IMGSENSOR_ID_EXPOSURE_ABSOLUTE, "Exposure time(100 usec)" + }, + + { + IMGSENSOR_ID_FOCUS_ABSOLUTE, "Focus(absolute value)" + }, + + { + IMGSENSOR_ID_FOCUS_RELATIVE, "Focus(relative value)" + }, + + { + IMGSENSOR_ID_FOCUS_AUTO, "Continuous Auto Focus" + }, + + { + IMGSENSOR_ID_ZOOM_ABSOLUTE, "Zoom(absolute value)" + }, + + { + IMGSENSOR_ID_ZOOM_RELATIVE, "Zoom(relative value)" + }, + + { + IMGSENSOR_ID_ZOOM_CONTINUOUS, "Continuous zoom" + }, + + { + IMGSENSOR_ID_IRIS_ABSOLUTE, "Iris(absolute value)" + }, + + { + IMGSENSOR_ID_IRIS_RELATIVE, "Iris(relative value)" + }, + + { + IMGSENSOR_ID_AUTO_N_PRESET_WB, "Preset white balance" + }, + + { + IMGSENSOR_ID_WIDE_DYNAMIC_RANGE, "Wide dynamic range" + }, + + { + IMGSENSOR_ID_IMG_STABILIZATION, "Image stabilization" + }, + + { + IMGSENSOR_ID_ISO_SENSITIVITY, "ISO sensitivity" + }, + + { + IMGSENSOR_ID_ISO_SENSITIVITY_AUTO, "Automatic ISO sensitivity" + }, + + { + IMGSENSOR_ID_EXPOSURE_METERING, "Photometry" + }, + + { + IMGSENSOR_ID_SPOT_POSITION, "Spot position" + }, + + { + IMGSENSOR_ID_3A_LOCK, "Lock AWB/AE" + }, + + { + IMGSENSOR_ID_AUTO_FOCUS_START, "Start single Auto Focus" + }, + + { + IMGSENSOR_ID_AUTO_FOCUS_STOP, "Stop single Auto Focus" + }, + + { + IMGSENSOR_ID_3A_PARAMETER, "3A parameter" + }, + + { + IMGSENSOR_ID_3A_STATUS, "3A status" + }, + + { + IMGSENSOR_ID_FLASH_LED_MODE, "LED mode" + }, + + { + IMGSENSOR_ID_JPEG_QUALITY, "JPEG compression quality" + } }; -static FAR struct imgsensor_s **g_video_registered_sensor = NULL; -static size_t g_video_registered_sensor_num; -static FAR struct imgdata_s *g_video_data = NULL; +static FAR struct imgsensor_s **g_capture_registered_sensor = NULL; +static size_t g_capture_registered_sensor_num; +static FAR struct imgdata_s *g_capture_data = NULL; /**************************************************************************** * Private Functions ****************************************************************************/ -static FAR video_type_inf_t * -get_video_type_inf(FAR video_mng_t *vmng, uint8_t type) +static FAR capture_type_inf_t * +get_capture_type_inf(FAR capture_mng_t *cmng, uint8_t type) { - FAR video_type_inf_t *type_inf; + FAR capture_type_inf_t *type_inf; switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - type_inf = &vmng->video_inf; + type_inf = &cmng->capture_inf; break; case V4L2_BUF_TYPE_STILL_CAPTURE: - type_inf = &vmng->still_inf; + type_inf = &cmng->still_inf; break; default: /* Error case */ @@ -400,31 +555,31 @@ get_video_type_inf(FAR video_mng_t *vmng, uint8_t type) return type_inf; } -static enum video_state_e -estimate_next_video_state(FAR video_mng_t *vmng, - enum video_state_transition_cause cause) +static enum capture_state_e +estimate_next_capture_state(FAR capture_mng_t *cmng, + enum capture_state_cause_e cause) { - enum video_state_e current_state = vmng->video_inf.state; + enum capture_state_e current_state = cmng->capture_inf.state; switch (cause) { - case CAUSE_VIDEO_STOP: - return VIDEO_STATE_STREAMOFF; + case CAUSE_CAPTURE_STOP: + return CAPTURE_STATE_STREAMOFF; - case CAUSE_VIDEO_START: - if (is_taking_still_picture(vmng)) + case CAUSE_CAPTURE_START: + if (is_taking_still_picture(cmng)) { - return VIDEO_STATE_STREAMON; + return CAPTURE_STATE_STREAMON; } else { - return VIDEO_STATE_CAPTURE; + return CAPTURE_STATE_CAPTURE; } case CAUSE_STILL_STOP: - if (current_state == VIDEO_STATE_STREAMON) + if (current_state == CAPTURE_STATE_STREAMON) { - return VIDEO_STATE_CAPTURE; + return CAPTURE_STATE_CAPTURE; } else { @@ -432,20 +587,20 @@ estimate_next_video_state(FAR video_mng_t *vmng, } case CAUSE_STILL_START: - if (current_state == VIDEO_STATE_CAPTURE) + if (current_state == CAPTURE_STATE_CAPTURE) { - return VIDEO_STATE_STREAMON; + return CAPTURE_STATE_STREAMON; } else { return current_state; } - case CAUSE_VIDEO_DQBUF: - if (current_state == VIDEO_STATE_STREAMON && - !is_taking_still_picture(vmng)) + case CAUSE_CAPTURE_DQBUF: + if (current_state == CAPTURE_STATE_STREAMON && + !is_taking_still_picture(cmng)) { - return VIDEO_STATE_CAPTURE; + return CAPTURE_STATE_CAPTURE; } else { @@ -569,36 +724,37 @@ static bool is_clipped(FAR struct v4l2_rect *clip) return ret; } -static void get_clipped_format(uint8_t nr_fmt, - FAR video_format_t *fmt, +static void get_clipped_format(uint8_t nr_fmt, + FAR video_format_t *fmt, FAR struct v4l2_rect *clip, - FAR video_format_t *c_fmt) + FAR video_format_t *c_fmt) { DEBUGASSERT(fmt && c_fmt); if (is_clipped(clip)) { - c_fmt[VIDEO_FMT_MAIN].width = clip->width; - c_fmt[VIDEO_FMT_MAIN].height = clip->height; - c_fmt[VIDEO_FMT_MAIN].pixelformat = fmt[VIDEO_FMT_MAIN].pixelformat; + c_fmt[CAPTURE_FMT_MAIN].width = clip->width; + c_fmt[CAPTURE_FMT_MAIN].height = clip->height; + c_fmt[CAPTURE_FMT_MAIN].pixelformat = + fmt[CAPTURE_FMT_MAIN].pixelformat; if (nr_fmt > 1) { /* Clipped size of thumbnail is - * small as ratio of main size and thumbnal size. + * small as ratio of main size and thumbnail size. */ - memcpy(&c_fmt[VIDEO_FMT_SUB], - &fmt[VIDEO_FMT_SUB], + memcpy(&c_fmt[CAPTURE_FMT_SUB], + &fmt[CAPTURE_FMT_SUB], sizeof(video_format_t)); - c_fmt[VIDEO_FMT_SUB].width = - (uint32_t)c_fmt[VIDEO_FMT_SUB].width * - clip->width / fmt[VIDEO_FMT_MAIN].width; + c_fmt[CAPTURE_FMT_SUB].width = + (uint32_t)c_fmt[CAPTURE_FMT_SUB].width * + clip->width / fmt[CAPTURE_FMT_MAIN].width; - c_fmt[VIDEO_FMT_SUB].height = - (uint32_t)c_fmt[VIDEO_FMT_SUB].height * - clip->height / fmt[VIDEO_FMT_MAIN].height; + c_fmt[CAPTURE_FMT_SUB].height = + (uint32_t)c_fmt[CAPTURE_FMT_SUB].height * + clip->height / fmt[CAPTURE_FMT_MAIN].height; } } else @@ -607,7 +763,7 @@ static void get_clipped_format(uint8_t nr_fmt, } } -static int start_capture(FAR video_mng_t *vmng, +static int start_capture(FAR struct capture_mng_s *cmng, enum v4l2_buf_type type, uint8_t nr_fmt, FAR video_format_t *fmt, @@ -615,88 +771,88 @@ static int start_capture(FAR video_mng_t *vmng, FAR struct v4l2_fract *interval, uintptr_t bufaddr, uint32_t bufsize) { - video_format_t c_fmt[MAX_VIDEO_FMT]; - imgdata_format_t df[MAX_VIDEO_FMT]; - imgsensor_format_t sf[MAX_VIDEO_FMT]; + video_format_t c_fmt[MAX_CAPTURE_FMT]; + imgdata_format_t df[MAX_CAPTURE_FMT]; + imgsensor_format_t sf[MAX_CAPTURE_FMT]; imgdata_interval_t di; imgsensor_interval_t si; - ASSERT(fmt && interval && vmng->imgsensor && vmng->imgdata); + ASSERT(fmt && interval && cmng->imgsensor && cmng->imgdata); get_clipped_format(nr_fmt, fmt, clip, c_fmt); - convert_to_imgdatafmt(&c_fmt[VIDEO_FMT_MAIN], &df[IMGDATA_FMT_MAIN]); - convert_to_imgdatafmt(&c_fmt[VIDEO_FMT_SUB], &df[IMGDATA_FMT_SUB]); + convert_to_imgdatafmt(&c_fmt[CAPTURE_FMT_MAIN], &df[IMGDATA_FMT_MAIN]); + convert_to_imgdatafmt(&c_fmt[CAPTURE_FMT_SUB], &df[IMGDATA_FMT_SUB]); convert_to_imgdatainterval(interval, &di); - convert_to_imgsensorfmt(&fmt[VIDEO_FMT_MAIN], &sf[IMGSENSOR_FMT_MAIN]); - convert_to_imgsensorfmt(&fmt[VIDEO_FMT_SUB], &sf[IMGSENSOR_FMT_SUB]); + convert_to_imgsensorfmt(&fmt[CAPTURE_FMT_MAIN], &sf[IMGSENSOR_FMT_MAIN]); + convert_to_imgsensorfmt(&fmt[CAPTURE_FMT_SUB], &sf[IMGSENSOR_FMT_SUB]); convert_to_imgsensorinterval(interval, &si); - IMGDATA_SET_BUF(vmng->imgdata, - nr_fmt, df, (FAR uint8_t *)bufaddr, bufsize); - IMGDATA_START_CAPTURE(vmng->imgdata, - nr_fmt, df, &di, video_complete_capture, vmng); - IMGSENSOR_START_CAPTURE(vmng->imgsensor, + IMGDATA_SET_BUF(cmng->imgdata, (FAR uint8_t *)bufaddr, bufsize); + IMGDATA_START_CAPTURE(cmng->imgdata, + nr_fmt, df, &di, complete_capture, cmng); + IMGSENSOR_START_CAPTURE(cmng->imgsensor, type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? IMGSENSOR_STREAM_TYPE_VIDEO : IMGSENSOR_STREAM_TYPE_STILL, nr_fmt, sf, &si); return OK; } -static void stop_capture(FAR video_mng_t *vmng, enum v4l2_buf_type type) +static void stop_capture(FAR struct capture_mng_s *cmng, + enum v4l2_buf_type type) { - ASSERT(vmng->imgsensor && vmng->imgdata); + ASSERT(cmng->imgsensor && cmng->imgdata); - IMGDATA_STOP_CAPTURE(vmng->imgdata); - IMGSENSOR_STOP_CAPTURE(vmng->imgsensor, - type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? - IMGSENSOR_STREAM_TYPE_VIDEO : IMGSENSOR_STREAM_TYPE_STILL); + IMGDATA_STOP_CAPTURE(cmng->imgdata); + IMGSENSOR_STOP_CAPTURE(cmng->imgsensor, + type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? + IMGSENSOR_STREAM_TYPE_VIDEO : IMGSENSOR_STREAM_TYPE_STILL); } -static void change_video_state(FAR video_mng_t *vmng, - enum video_state_e next_state) +static void change_capture_state(FAR capture_mng_t *cmng, + enum capture_state_e next_state) { - enum video_state_e current_state = vmng->video_inf.state; - enum video_state_e updated_next_state = next_state; + enum capture_state_e current_state = cmng->capture_inf.state; + enum capture_state_e updated_next_state = next_state; - if (current_state != VIDEO_STATE_CAPTURE && - next_state == VIDEO_STATE_CAPTURE) + if (current_state != CAPTURE_STATE_CAPTURE && + next_state == CAPTURE_STATE_CAPTURE) { FAR vbuf_container_t *container = - video_framebuff_get_vacant_container(&vmng->video_inf.bufinf); + video_framebuff_get_vacant_container(&cmng->capture_inf.bufinf); if (container != NULL) { - vmng->video_inf.seqnum = 0; - start_capture(vmng, + cmng->capture_inf.seqnum = 0; + start_capture(cmng, V4L2_BUF_TYPE_VIDEO_CAPTURE, - vmng->video_inf.nr_fmt, - vmng->video_inf.fmt, - &vmng->video_inf.clip, - &vmng->video_inf.frame_interval, + cmng->capture_inf.nr_fmt, + cmng->capture_inf.fmt, + &cmng->capture_inf.clip, + &cmng->capture_inf.frame_interval, container->buf.m.userptr, container->buf.length); } else { - updated_next_state = VIDEO_STATE_STREAMON; + updated_next_state = CAPTURE_STATE_STREAMON; } } - else if (current_state == VIDEO_STATE_CAPTURE && - next_state != VIDEO_STATE_CAPTURE) + else if (current_state == CAPTURE_STATE_CAPTURE && + next_state != CAPTURE_STATE_CAPTURE) { - stop_capture(vmng, V4L2_BUF_TYPE_VIDEO_CAPTURE); + stop_capture(cmng, V4L2_BUF_TYPE_VIDEO_CAPTURE); } - vmng->video_inf.state = updated_next_state; + cmng->capture_inf.state = updated_next_state; } -static bool is_taking_still_picture(FAR video_mng_t *vmng) +static bool is_taking_still_picture(FAR capture_mng_t *cmng) { - return vmng->still_inf.state == VIDEO_STATE_STREAMON || - vmng->still_inf.state == VIDEO_STATE_CAPTURE; + return cmng->still_inf.state == CAPTURE_STATE_STREAMON || + cmng->still_inf.state == CAPTURE_STATE_CAPTURE; } -static bool is_bufsize_sufficient(FAR video_mng_t *vmng, uint32_t bufsize) +static bool is_bufsize_sufficient(FAR capture_mng_t *cmng, uint32_t bufsize) { /* Depend on format, frame size, and JPEG compression quality */ @@ -717,32 +873,32 @@ static void initialize_frame_setting(FAR struct imgsensor_s *imgsensor, { if (imgsensor->frmsizes[0].type == V4L2_FRMSIZE_TYPE_DISCRETE) { - fmt[VIDEO_FMT_MAIN].width = + fmt[CAPTURE_FMT_MAIN].width = imgsensor->frmsizes[0].discrete.width; - fmt[VIDEO_FMT_MAIN].height = + fmt[CAPTURE_FMT_MAIN].height = imgsensor->frmsizes[0].discrete.height; } else { - fmt[VIDEO_FMT_MAIN].width = + fmt[CAPTURE_FMT_MAIN].width = imgsensor->frmsizes[0].stepwise.min_width; - fmt[VIDEO_FMT_MAIN].height = + fmt[CAPTURE_FMT_MAIN].height = imgsensor->frmsizes[0].stepwise.min_height; } } else { - fmt[VIDEO_FMT_MAIN].width = VIDEO_HSIZE_QVGA; - fmt[VIDEO_FMT_MAIN].height = VIDEO_VSIZE_QVGA; + fmt[CAPTURE_FMT_MAIN].width = VIDEO_HSIZE_QVGA; + fmt[CAPTURE_FMT_MAIN].height = VIDEO_VSIZE_QVGA; } if (imgsensor && imgsensor->fmtdescs) { - fmt[VIDEO_FMT_MAIN].pixelformat = imgsensor->fmtdescs[0].pixelformat; + fmt[CAPTURE_FMT_MAIN].pixelformat = imgsensor->fmtdescs[0].pixelformat; } else { - fmt[VIDEO_FMT_MAIN].pixelformat = V4L2_PIX_FMT_UYVY; + fmt[CAPTURE_FMT_MAIN].pixelformat = V4L2_PIX_FMT_UYVY; } if (imgsensor && imgsensor->frmintervals) @@ -769,11 +925,11 @@ static void initialize_frame_setting(FAR struct imgsensor_s *imgsensor, } } -static void initialize_streamresources(FAR video_type_inf_t *type_inf, +static void initialize_streamresources(FAR capture_type_inf_t *type_inf, FAR struct imgsensor_s *imgsensor) { - memset(type_inf, 0, sizeof(video_type_inf_t)); - type_inf->remaining_capnum = VIDEO_REMAINING_CAPNUM_INFINITY; + memset(type_inf, 0, sizeof(capture_type_inf_t)); + type_inf->remaining_capnum = REMAINING_CAPNUM_INFINITY; nxmutex_init(&type_inf->lock_state); nxsem_init(&type_inf->wait_capture.dqbuf_wait_flg, 0, 0); initialize_frame_setting(imgsensor, &type_inf->nr_fmt, @@ -782,19 +938,19 @@ static void initialize_streamresources(FAR video_type_inf_t *type_inf, video_framebuff_init(&type_inf->bufinf); } -static int32_t get_default_value(FAR video_mng_t *vmng, uint32_t id) +static int32_t get_default_value(FAR capture_mng_t *cmng, uint32_t id) { imgsensor_supported_value_t value; int ret; - if (vmng->imgsensor == NULL) + if (cmng->imgsensor == NULL) { /* Don't care(unsupported parameter) */ return 0; } - ret = IMGSENSOR_GET_SUPPORTED_VALUE(vmng->imgsensor, id, &value); + ret = IMGSENSOR_GET_SUPPORTED_VALUE(cmng->imgsensor, id, &value); if (ret != OK) { /* Don't care(unsupported parameter) */ @@ -820,7 +976,8 @@ static int32_t get_default_value(FAR video_mng_t *vmng, uint32_t id) } } -static int32_t initialize_scene_gamma(FAR video_mng_t *vmng, uint8_t **gamma) +static int32_t initialize_scene_gamma(FAR capture_mng_t *cmng, + FAR uint8_t **gamma) { imgsensor_supported_value_t sup_val; imgsensor_value_t val; @@ -829,9 +986,9 @@ static int32_t initialize_scene_gamma(FAR video_mng_t *vmng, uint8_t **gamma) *gamma = NULL; - ASSERT(vmng->imgsensor); + ASSERT(cmng->imgsensor); - ret = IMGSENSOR_GET_SUPPORTED_VALUE(vmng->imgsensor, + ret = IMGSENSOR_GET_SUPPORTED_VALUE(cmng->imgsensor, IMGSENSOR_ID_GAMMA_CURVE, &sup_val); if (ret != OK) { @@ -878,136 +1035,138 @@ static int32_t initialize_scene_gamma(FAR video_mng_t *vmng, uint8_t **gamma) *gamma = kmm_malloc(sz); val.p_u8 = (FAR uint8_t *)*gamma; - IMGSENSOR_GET_VALUE(vmng->imgsensor, IMGSENSOR_ID_GAMMA_CURVE, sz, &val); + IMGSENSOR_GET_VALUE(cmng->imgsensor, IMGSENSOR_ID_GAMMA_CURVE, sz, &val); return sz; } -static int initialize_scene_parameter(FAR video_mng_t *vmng, +static int initialize_scene_parameter(FAR capture_mng_t *cmng, enum v4l2_scene_mode mode, - video_scene_params_t **vsp) + FAR capture_scene_params_t **vsp) { - FAR video_scene_params_t *sp = kmm_malloc(sizeof(video_scene_params_t)); + FAR capture_scene_params_t *sp = + kmm_malloc(sizeof(capture_scene_params_t)); + if (!sp) { return -ENOMEM; } - sp->brightness = get_default_value(vmng, IMGSENSOR_ID_BRIGHTNESS); - sp->contrast = get_default_value(vmng, IMGSENSOR_ID_CONTRAST); - sp->saturation = get_default_value(vmng, IMGSENSOR_ID_SATURATION); - sp->hue = get_default_value(vmng, IMGSENSOR_ID_HUE); - sp->awb = get_default_value(vmng, + sp->brightness = get_default_value(cmng, IMGSENSOR_ID_BRIGHTNESS); + sp->contrast = get_default_value(cmng, IMGSENSOR_ID_CONTRAST); + sp->saturation = get_default_value(cmng, IMGSENSOR_ID_SATURATION); + sp->hue = get_default_value(cmng, IMGSENSOR_ID_HUE); + sp->awb = get_default_value(cmng, IMGSENSOR_ID_AUTO_WHITE_BALANCE); - sp->red = get_default_value(vmng, IMGSENSOR_ID_RED_BALANCE); - sp->blue = get_default_value(vmng, IMGSENSOR_ID_BLUE_BALANCE); - sp->gamma = get_default_value(vmng, IMGSENSOR_ID_GAMMA); - sp->gamma_curve_sz = initialize_scene_gamma(vmng, &sp->gamma_curve); - sp->ev = get_default_value(vmng, IMGSENSOR_ID_EXPOSURE); - sp->hflip_video = get_default_value(vmng, IMGSENSOR_ID_HFLIP_VIDEO); - sp->vflip_video = get_default_value(vmng, IMGSENSOR_ID_VFLIP_VIDEO); - sp->hflip_still = get_default_value(vmng, IMGSENSOR_ID_HFLIP_STILL); - sp->vflip_still = get_default_value(vmng, IMGSENSOR_ID_VFLIP_STILL); - sp->sharpness = get_default_value(vmng, IMGSENSOR_ID_SHARPNESS); - sp->colorfx = get_default_value(vmng, IMGSENSOR_ID_COLORFX); - sp->auto_brightness = get_default_value(vmng, IMGSENSOR_ID_AUTOBRIGHTNESS); - sp->rotate = get_default_value(vmng, IMGSENSOR_ID_ROTATE); - sp->ae = get_default_value(vmng, IMGSENSOR_ID_EXPOSURE_AUTO); - sp->exposure_time = get_default_value(vmng, + sp->red = get_default_value(cmng, IMGSENSOR_ID_RED_BALANCE); + sp->blue = get_default_value(cmng, IMGSENSOR_ID_BLUE_BALANCE); + sp->gamma = get_default_value(cmng, IMGSENSOR_ID_GAMMA); + sp->gamma_curve_sz = initialize_scene_gamma(cmng, &sp->gamma_curve); + sp->ev = get_default_value(cmng, IMGSENSOR_ID_EXPOSURE); + sp->hflip_video = get_default_value(cmng, IMGSENSOR_ID_HFLIP_VIDEO); + sp->vflip_video = get_default_value(cmng, IMGSENSOR_ID_VFLIP_VIDEO); + sp->hflip_still = get_default_value(cmng, IMGSENSOR_ID_HFLIP_STILL); + sp->vflip_still = get_default_value(cmng, IMGSENSOR_ID_VFLIP_STILL); + sp->sharpness = get_default_value(cmng, IMGSENSOR_ID_SHARPNESS); + sp->colorfx = get_default_value(cmng, IMGSENSOR_ID_COLORFX); + sp->auto_brightness = get_default_value(cmng, IMGSENSOR_ID_AUTOBRIGHTNESS); + sp->rotate = get_default_value(cmng, IMGSENSOR_ID_ROTATE); + sp->ae = get_default_value(cmng, IMGSENSOR_ID_EXPOSURE_AUTO); + sp->exposure_time = get_default_value(cmng, IMGSENSOR_ID_EXPOSURE_ABSOLUTE); - sp->focus = get_default_value(vmng, IMGSENSOR_ID_FOCUS_ABSOLUTE); - sp->af = get_default_value(vmng, IMGSENSOR_ID_FOCUS_AUTO); - sp->zoom = get_default_value(vmng, IMGSENSOR_ID_ZOOM_ABSOLUTE); - sp->iris = get_default_value(vmng, IMGSENSOR_ID_IRIS_ABSOLUTE); - sp->wb = get_default_value(vmng, + sp->focus = get_default_value(cmng, IMGSENSOR_ID_FOCUS_ABSOLUTE); + sp->af = get_default_value(cmng, IMGSENSOR_ID_FOCUS_AUTO); + sp->zoom = get_default_value(cmng, IMGSENSOR_ID_ZOOM_ABSOLUTE); + sp->iris = get_default_value(cmng, IMGSENSOR_ID_IRIS_ABSOLUTE); + sp->wb = get_default_value(cmng, IMGSENSOR_ID_AUTO_N_PRESET_WB); - sp->wdr = get_default_value(vmng, + sp->wdr = get_default_value(cmng, IMGSENSOR_ID_WIDE_DYNAMIC_RANGE); - sp->stabilization = get_default_value(vmng, + sp->stabilization = get_default_value(cmng, IMGSENSOR_ID_IMG_STABILIZATION); - sp->iso_auto = get_default_value(vmng, + sp->iso_auto = get_default_value(cmng, IMGSENSOR_ID_ISO_SENSITIVITY_AUTO); - sp->iso = get_default_value(vmng, + sp->iso = get_default_value(cmng, IMGSENSOR_ID_ISO_SENSITIVITY); - sp->meter = get_default_value(vmng, + sp->meter = get_default_value(cmng, IMGSENSOR_ID_EXPOSURE_METERING); - sp->threea_lock = get_default_value(vmng, IMGSENSOR_ID_3A_LOCK); - sp->led = get_default_value(vmng, IMGSENSOR_ID_FLASH_LED_MODE); - sp->jpeg_quality = get_default_value(vmng, IMGSENSOR_ID_JPEG_QUALITY); + sp->threea_lock = get_default_value(cmng, IMGSENSOR_ID_3A_LOCK); + sp->led = get_default_value(cmng, IMGSENSOR_ID_FLASH_LED_MODE); + sp->jpeg_quality = get_default_value(cmng, IMGSENSOR_ID_JPEG_QUALITY); *vsp = sp; return OK; } -static void initialize_scenes_parameter(FAR video_mng_t *vmng) +static void initialize_scenes_parameter(FAR capture_mng_t *cmng) { - memset(vmng->video_scene_param, - 0, sizeof(vmng->video_scene_param)); + memset(cmng->capture_scene_param, + 0, sizeof(cmng->capture_scene_param)); - initialize_scene_parameter(vmng, V4L2_SCENE_MODE_NONE, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, V4L2_SCENE_MODE_NONE, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #ifdef CONFIG_VIDEO_SCENE_BACKLIGHT - initialize_scene_parameter(vmng, V4L2_SCENE_MODE_BACKLIGHT, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, V4L2_SCENE_MODE_BACKLIGHT, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_BACKLIGHT */ #ifdef CONFIG_VIDEO_SCENE_BEACHSNOW - initialize_scene_parameter(vmng, CONFIG_VIDEO_SCENE_BEACHSNOW, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, CONFIG_VIDEO_SCENE_BEACHSNOW, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_BEACHSNOW */ #ifdef CONFIG_VIDEO_SCENE_CANDLELIGHT - initialize_scene_parameter(vmng, CONFIG_VIDEO_SCENE_CANDLELIGHT, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, CONFIG_VIDEO_SCENE_CANDLELIGHT, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_CANDLELIGHT */ #ifdef CONFIG_VIDEO_SCENE_DAWNDUSK - initialize_scene_parameter(vmng, CONFIG_VIDEO_SCENE_DAWNDUSK, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, CONFIG_VIDEO_SCENE_DAWNDUSK, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_DAWNDUSK */ #ifdef CONFIG_VIDEO_SCENE_FALLCOLORS - initialize_scene_parameter(vmng, CONFIG_VIDEO_SCENE_FALLCOLORS, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, CONFIG_VIDEO_SCENE_FALLCOLORS, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_FALLCOLORS */ #ifdef CONFIG_VIDEO_SCENE_FIREWORKS - initialize_scene_parameter(vmng, CONFIG_VIDEO_SCENE_FIREWORKS, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, CONFIG_VIDEO_SCENE_FIREWORKS, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_FIREWORKS */ #ifdef CONFIG_VIDEO_SCENE_LANDSCAPE - initialize_scene_parameter(vmng, CONFIG_VIDEO_SCENE_LANDSCAPE, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, CONFIG_VIDEO_SCENE_LANDSCAPE, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_LANDSCAPE */ #ifdef CONFIG_VIDEO_SCENE_NIGHT - initialize_scene_parameter(vmng, CONFIG_VIDEO_SCENE_NIGHT, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, CONFIG_VIDEO_SCENE_NIGHT, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_NIGHT */ #ifdef CONFIG_VIDEO_SCENE_PARTYINDOOR - initialize_scene_parameter(vmng, CONFIG_VIDEO_SCENE_PARTYINDOOR, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, CONFIG_VIDEO_SCENE_PARTYINDOOR, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_PARTYINDOOR */ #ifdef CONFIG_VIDEO_SCENE_PORTRAIT - initialize_scene_parameter(vmng, CONFIG_VIDEO_SCENE_PORTRAIT, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, CONFIG_VIDEO_SCENE_PORTRAIT, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_PORTRAIT */ #ifdef CONFIG_VIDEO_SCENE_SPORTS - initialize_scene_parameter(vmng, CONFIG_VIDEO_SCENE_SPORTS, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, CONFIG_VIDEO_SCENE_SPORTS, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_SPORTS */ #ifdef CONFIG_VIDEO_SCENE_SUNSET - initialize_scene_parameter(vmng, CONFIG_VIDEO_SCENE_SUNSET, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, CONFIG_VIDEO_SCENE_SUNSET, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_SUNSET */ #ifdef CONFIG_VIDEO_SCENE_TEXT - initialize_scene_parameter(vmng, CONFIG_VIDEO_SCENE_TEXT, - &vmng->video_scene_param[vmng->video_scence_num++]); + initialize_scene_parameter(cmng, CONFIG_VIDEO_SCENE_TEXT, + &cmng->capture_scene_param[cmng->capture_scence_num++]); #endif /* CONFIG_VIDEO_SCENE_TEXT */ } -static void initialize_resources(FAR video_mng_t *vmng) +static void initialize_resources(FAR capture_mng_t *cmng) { - initialize_streamresources(&vmng->video_inf, vmng->imgsensor); - initialize_streamresources(&vmng->still_inf, vmng->imgsensor); - initialize_scenes_parameter(vmng); + initialize_streamresources(&cmng->capture_inf, cmng->imgsensor); + initialize_streamresources(&cmng->still_inf, cmng->imgsensor); + initialize_scenes_parameter(cmng); } -static void cleanup_streamresources(FAR video_type_inf_t *type_inf) +static void cleanup_streamresources(FAR capture_type_inf_t *type_inf) { video_framebuff_uninit(&type_inf->bufinf); nxsem_destroy(&type_inf->wait_capture.dqbuf_wait_flg); @@ -1019,9 +1178,9 @@ static void cleanup_streamresources(FAR video_type_inf_t *type_inf) } } -static void cleanup_scene_parameter(FAR video_scene_params_t **vsp) +static void cleanup_scene_parameter(FAR capture_scene_params_t **vsp) { - FAR video_scene_params_t *sp = *vsp; + FAR capture_scene_params_t *sp = *vsp; ASSERT(sp); if (sp->gamma_curve != NULL) @@ -1035,37 +1194,37 @@ static void cleanup_scene_parameter(FAR video_scene_params_t **vsp) *vsp = NULL; } -static void cleanup_scenes_parameter(FAR video_mng_t *vmng) +static void cleanup_scenes_parameter(FAR capture_mng_t *cmng) { int i; - for (i = 0; i < vmng->video_scence_num; i++) + for (i = 0; i < cmng->capture_scence_num; i++) { - cleanup_scene_parameter(&vmng->video_scene_param[i]); + cleanup_scene_parameter(&cmng->capture_scene_param[i]); } - vmng->video_scence_num = 0; + cmng->capture_scence_num = 0; } -static void cleanup_resources(FAR video_mng_t *vmng) +static void cleanup_resources(FAR capture_mng_t *cmng) { /* If in capture, stop */ - if (vmng->video_inf.state == VIDEO_STATE_CAPTURE) + if (cmng->capture_inf.state == CAPTURE_STATE_CAPTURE) { - stop_capture(vmng, V4L2_BUF_TYPE_VIDEO_CAPTURE); + stop_capture(cmng, V4L2_BUF_TYPE_VIDEO_CAPTURE); } - if (vmng->still_inf.state == VIDEO_STATE_CAPTURE) + if (cmng->still_inf.state == CAPTURE_STATE_CAPTURE) { - stop_capture(vmng, V4L2_BUF_TYPE_STILL_CAPTURE); + stop_capture(cmng, V4L2_BUF_TYPE_STILL_CAPTURE); } /* Clean up resource */ - cleanup_streamresources(&vmng->video_inf); - cleanup_streamresources(&vmng->still_inf); - cleanup_scenes_parameter(vmng); + cleanup_streamresources(&cmng->capture_inf); + cleanup_streamresources(&cmng->still_inf); + cleanup_scenes_parameter(cmng); } static bool is_sem_waited(FAR sem_t *sem) @@ -1075,2034 +1234,2085 @@ static bool is_sem_waited(FAR sem_t *sem) return nxsem_get_value(sem, &semcount) == OK && semcount < 0; } -static FAR struct imgsensor_s * -get_connected_imgsensor(FAR struct imgsensor_s **sensors, - size_t sensor_num) +static int validate_frame_setting(FAR capture_mng_t *cmng, + enum v4l2_buf_type type, + uint8_t nr_fmt, + FAR video_format_t *vfmt, + FAR struct v4l2_rect *clip, + FAR struct v4l2_fract *interval) { - FAR struct imgsensor_s *sensor = NULL; - int i; + video_format_t c_fmt[MAX_CAPTURE_FMT]; + imgdata_format_t df[MAX_CAPTURE_FMT]; + imgsensor_format_t sf[MAX_CAPTURE_FMT]; + imgdata_interval_t di; + imgsensor_interval_t si; + int ret; - for (i = 0; i < sensor_num; i++) + ASSERT(vfmt && interval && cmng->imgsensor && cmng->imgdata); + + /* Return OK only in case both image data driver and + * image sensor driver support. + */ + + get_clipped_format(nr_fmt, vfmt, clip, c_fmt); + + convert_to_imgdatafmt(&c_fmt[CAPTURE_FMT_MAIN], &df[IMGDATA_FMT_MAIN]); + convert_to_imgdatafmt(&c_fmt[CAPTURE_FMT_SUB], &df[IMGDATA_FMT_SUB]); + convert_to_imgdatainterval(interval, &di); + convert_to_imgsensorfmt(&vfmt[CAPTURE_FMT_MAIN], &sf[IMGSENSOR_FMT_MAIN]); + convert_to_imgsensorfmt(&vfmt[CAPTURE_FMT_SUB], &sf[IMGSENSOR_FMT_SUB]); + convert_to_imgsensorinterval(interval, &si); + + ret = IMGSENSOR_VALIDATE_FRAME_SETTING(cmng->imgsensor, + type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? + IMGSENSOR_STREAM_TYPE_VIDEO : IMGSENSOR_STREAM_TYPE_STILL, + nr_fmt, sf, &si); + if (ret != OK) { - if (sensors[i] && - IMGSENSOR_IS_AVAILABLE(sensors[i])) - { - sensor = sensors[i]; - break; - } + return ret; } - return sensor; + return IMGDATA_VALIDATE_FRAME_SETTING(cmng->imgdata, nr_fmt, df, &di); } -static int video_open(FAR struct file *filep) +static size_t get_bufsize(FAR video_format_t *vf) { - FAR struct inode *inode = filep->f_inode; - FAR video_mng_t *priv = inode->i_private; - int ret = OK; + size_t ret = vf->width * vf->height; - nxmutex_lock(&priv->lock_open_num); - if (priv->open_num == 0) + switch (vf->pixelformat) { - /* Only in first execution, open device */ - - ret = IMGSENSOR_INIT(priv->imgsensor); - if (ret == OK) - { - ret = IMGDATA_INIT(priv->imgdata); - if (ret == OK) - { - initialize_resources(priv); - } - } - else - { - ret = -ENODEV; - } + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_YUV420: + return ret * 3 / 2; + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_JPEG: + default: + return ret * 2; } +} - /* In second or later execution, ret is initial value(=OK) */ - - if (ret == OK) - { - priv->open_num++; - } +static size_t get_heapsize(FAR capture_type_inf_t *type_inf) +{ + return type_inf->bufinf.container_size * + get_bufsize(&type_inf->fmt[CAPTURE_FMT_MAIN]); +} - nxmutex_unlock(&priv->lock_open_num); - return ret; +static bool validate_clip_range(int32_t pos, uint32_t c_sz, uint16_t frm_sz) +{ + return pos >= 0 && c_sz <= frm_sz && pos + c_sz <= frm_sz; } -static int video_close(FAR struct file *filep) +static bool validate_clip_setting(FAR struct v4l2_rect *clip, + FAR video_format_t *fmt) { - FAR struct inode *inode = filep->f_inode; - FAR video_mng_t *priv = inode->i_private; + DEBUGASSERT(clip && fmt); + + /* Not permit the setting which do not fit inside frame size. */ + + return validate_clip_range(clip->left, clip->width, fmt->width) && + validate_clip_range(clip->top, clip->height, fmt->height); +} - nxmutex_lock(&priv->lock_open_num); +static void set_parameter_name(uint32_t id, FAR char *name) +{ + int size = + sizeof(g_capture_parameter_name) / sizeof(capture_parameter_name_t); + int cnt; - if (--priv->open_num == 0) + for (cnt = 0; cnt < size; cnt++) { - cleanup_resources(priv); - IMGSENSOR_UNINIT(priv->imgsensor); - IMGDATA_UNINIT(priv->imgdata); -#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS - if (priv->unlinked) + if (g_capture_parameter_name[cnt].id == id) { - nxmutex_unlock(&priv->lock_open_num); - nxmutex_destroy(&priv->lock_open_num); - kmm_free(priv->devpath); - kmm_free(priv); - inode->i_private = NULL; - return OK; + break; } - -#endif } - nxmutex_unlock(&priv->lock_open_num); - return OK; + ASSERT(cnt < size); + + /* copy size = 32 is due to V4L2 specification. */ + + strlcpy(name, g_capture_parameter_name[cnt].name, 32); } -static ssize_t video_read(FAR struct file *filep, - FAR char *buffer, size_t buflen) +static int set_intvalue(FAR struct capture_mng_s *cmng, + uint32_t id, int32_t value32) { - return -ENOTSUP; + imgsensor_value_t value; + + ASSERT(cmng->imgsensor); + + value.value32 = value32; + return IMGSENSOR_SET_VALUE(cmng->imgsensor, id, sizeof(int32_t), value); } -static ssize_t video_write(FAR struct file *filep, - FAR const char *buffer, size_t buflen) +static int set_pvalue(FAR struct capture_mng_s *cmng, + uint32_t id, int size, void *pval) { - return -ENOTSUP; + imgsensor_value_t value; + + ASSERT(cmng->imgsensor); + + value.p_u8 = (FAR uint8_t *)pval; + return IMGSENSOR_SET_VALUE(cmng->imgsensor, id, size, value); } -#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS -static int video_unlink(FAR struct inode *inode) +static capture_scene_params_t *search_scene_param(FAR capture_mng_t *cmng, + enum v4l2_scene_mode mode) { - FAR video_mng_t *priv = inode->i_private; - nxmutex_lock(&priv->lock_open_num); - if (priv->open_num == 0) - { - nxmutex_unlock(&priv->lock_open_num); - nxmutex_destroy(&priv->lock_open_num); - kmm_free(priv->devpath); - kmm_free(priv); - inode->i_private = NULL; - } - else + int i; + + for (i = 0; i < cmng->capture_scence_num; i++) { - priv->unlinked = true; - nxmutex_unlock(&priv->lock_open_num); + if (cmng->capture_scene_param[i]->mode == mode) + { + return cmng->capture_scene_param[i]; + } } - return OK; + return NULL; } -#endif -static int video_querycap(FAR video_mng_t *vmng, - FAR struct v4l2_capability *cap) +static int reflect_scene_parameter(FAR capture_mng_t *cmng, + enum v4l2_scene_mode mode) { - FAR const char *name; + capture_scene_params_t *sp; - ASSERT(vmng->imgsensor); - - if (cap == NULL) + sp = search_scene_param(cmng, mode); + if (sp == NULL) { + /* Unsupported scene mode */ + return -EINVAL; } - name = IMGSENSOR_GET_DRIVER_NAME(vmng->imgsensor); - if (name == NULL) + set_intvalue(cmng, IMGSENSOR_ID_BRIGHTNESS, sp->brightness); + set_intvalue(cmng, IMGSENSOR_ID_CONTRAST, sp->contrast); + set_intvalue(cmng, IMGSENSOR_ID_SATURATION, sp->saturation); + set_intvalue(cmng, IMGSENSOR_ID_HUE , sp->hue); + set_intvalue(cmng, IMGSENSOR_ID_AUTO_WHITE_BALANCE, sp->awb); + set_intvalue(cmng, IMGSENSOR_ID_RED_BALANCE , sp->red); + set_intvalue(cmng, IMGSENSOR_ID_BLUE_BALANCE, sp->blue); + set_intvalue(cmng, IMGSENSOR_ID_GAMMA, sp->gamma); + set_pvalue(cmng, IMGSENSOR_ID_GAMMA_CURVE, + sp->gamma_curve_sz, sp->gamma_curve); + set_intvalue(cmng, IMGSENSOR_ID_EXPOSURE, sp->ev); + set_intvalue(cmng, IMGSENSOR_ID_HFLIP_VIDEO, sp->hflip_video); + set_intvalue(cmng, IMGSENSOR_ID_VFLIP_VIDEO, sp->vflip_video); + set_intvalue(cmng, IMGSENSOR_ID_HFLIP_STILL, sp->hflip_still); + set_intvalue(cmng, IMGSENSOR_ID_VFLIP_STILL, sp->vflip_still); + set_intvalue(cmng, IMGSENSOR_ID_SHARPNESS, sp->sharpness); + set_intvalue(cmng, IMGSENSOR_ID_COLORFX, sp->colorfx); + set_intvalue(cmng, IMGSENSOR_ID_AUTOBRIGHTNESS, sp->auto_brightness); + set_intvalue(cmng, IMGSENSOR_ID_ROTATE, sp->rotate); + set_intvalue(cmng, IMGSENSOR_ID_EXPOSURE_AUTO, sp->ae); + if (sp->ae == V4L2_EXPOSURE_MANUAL || + sp->ae == V4L2_EXPOSURE_SHUTTER_PRIORITY) { - return -ENOTTY; + set_intvalue(cmng, IMGSENSOR_ID_EXPOSURE_ABSOLUTE, sp->exposure_time); } - memset(cap, 0, sizeof(struct v4l2_capability)); + set_intvalue(cmng, IMGSENSOR_ID_FOCUS_ABSOLUTE, sp->focus); + set_intvalue(cmng, IMGSENSOR_ID_FOCUS_AUTO, sp->af); + set_intvalue(cmng, IMGSENSOR_ID_ZOOM_ABSOLUTE, sp->zoom); + if (sp->ae == V4L2_EXPOSURE_MANUAL || + sp->ae == V4L2_EXPOSURE_APERTURE_PRIORITY) + { + set_intvalue(cmng, IMGSENSOR_ID_IRIS_ABSOLUTE, sp->iris); + } - /* cap->driver needs to be NULL-terminated. */ + set_intvalue(cmng, IMGSENSOR_ID_AUTO_N_PRESET_WB, sp->wb); + set_intvalue(cmng, IMGSENSOR_ID_WIDE_DYNAMIC_RANGE, sp->wdr); + set_intvalue(cmng, IMGSENSOR_ID_IMG_STABILIZATION, sp->stabilization); + set_intvalue(cmng, IMGSENSOR_ID_ISO_SENSITIVITY_AUTO, sp->iso_auto); + if (sp->iso_auto == V4L2_ISO_SENSITIVITY_MANUAL) + { + set_intvalue(cmng, IMGSENSOR_ID_ISO_SENSITIVITY, sp->iso); + } - strlcpy((FAR char *)cap->driver, name, sizeof(cap->driver)); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + set_intvalue(cmng, IMGSENSOR_ID_EXPOSURE_METERING, sp->meter); + set_intvalue(cmng, IMGSENSOR_ID_3A_LOCK, sp->threea_lock); + set_intvalue(cmng, IMGSENSOR_ID_FLASH_LED_MODE, sp->led); + set_intvalue(cmng, IMGSENSOR_ID_JPEG_QUALITY, sp->jpeg_quality); + cmng->capture_scene_mode = mode; return OK; } -static int video_g_input(FAR int *num) +static int read_scene_param(FAR struct capture_mng_s *cmng, + enum v4l2_scene_mode mode, + uint32_t id, + struct v4l2_ext_control *control) { - *num = 0; - return OK; -} + imgsensor_supported_value_t value; + capture_scene_params_t *sp; + int ret = OK; -static int video_enum_input(FAR video_mng_t *vmng, - FAR struct v4l2_input *input) -{ - FAR const char *name; + ASSERT(cmng->imgsensor); - ASSERT(vmng->imgsensor); - - if (input->index > 0) + if (control == NULL) { return -EINVAL; } - name = IMGSENSOR_GET_DRIVER_NAME(vmng->imgsensor); - if (name == NULL) + sp = search_scene_param(cmng, mode); + if (sp == NULL) { - return -ENOTTY; - } - - memset(input, 0, sizeof(struct v4l2_input)); - strlcpy((FAR char *)input->name, name, sizeof(input->name)); - input->type = V4L2_INPUT_TYPE_CAMERA; - - return OK; -} - -static int video_reqbufs(FAR struct video_mng_s *vmng, - FAR struct v4l2_requestbuffers *reqbufs) -{ - FAR video_type_inf_t *type_inf; - irqstate_t flags; - int ret = OK; + /* Unsupported scene mode */ - if (vmng == NULL || reqbufs == NULL) - { return -EINVAL; } - type_inf = get_video_type_inf(vmng, reqbufs->type); - if (type_inf == NULL) + ret = IMGSENSOR_GET_SUPPORTED_VALUE(cmng->imgsensor, id, &value); + if (ret < 0) { - return -EINVAL; - } + /* Unsupported camera parameter */ - flags = enter_critical_section(); + return ret; + } - if (type_inf->state == VIDEO_STATE_CAPTURE) + switch (id) { - /* In capture, REQBUFS is not permitted */ + case IMGSENSOR_ID_BRIGHTNESS: + control->value = sp->brightness; + break; - ret = -EPERM; - } - else - { - if (reqbufs->count > V4L2_REQBUFS_COUNT_MAX) - { - reqbufs->count = V4L2_REQBUFS_COUNT_MAX; - } + case IMGSENSOR_ID_CONTRAST: + control->value = sp->contrast; + break; - video_framebuff_change_mode(&type_inf->bufinf, reqbufs->mode); - ret = video_framebuff_realloc_container(&type_inf->bufinf, - reqbufs->count); - if (ret == OK && reqbufs->memory == V4L2_MEMORY_MMAP) - { - if (type_inf->bufheap != NULL) - { - kumm_free(type_inf->bufheap); - } + case IMGSENSOR_ID_SATURATION: + control->value = sp->saturation; + break; - type_inf->bufheap = kumm_memalign(32, - reqbufs->count * get_bufsize(&type_inf->fmt[VIDEO_FMT_MAIN])); - if (type_inf->bufheap == NULL) - { - ret = -ENOMEM; - } - } - } + case IMGSENSOR_ID_HUE: + control->value = sp->hue; + break; - leave_critical_section(flags); - return ret; -} + case IMGSENSOR_ID_AUTO_WHITE_BALANCE: + control->value = sp->awb; + break; -static int video_querybuf(FAR struct video_mng_s *vmng, - FAR struct v4l2_buffer *buf) -{ - FAR video_type_inf_t *type_inf; + case IMGSENSOR_ID_RED_BALANCE: + control->value = sp->red; + break; - if (vmng == NULL || buf == NULL || buf->memory != V4L2_MEMORY_MMAP) - { - return -EINVAL; - } + case IMGSENSOR_ID_BLUE_BALANCE: + control->value = sp->blue; + break; - type_inf = get_video_type_inf(vmng, buf->type); - if (type_inf == NULL) - { - return -EINVAL; - } + case IMGSENSOR_ID_GAMMA: + control->value = sp->gamma; + break; - if (buf->index >= type_inf->bufinf.container_size) - { - return -EINVAL; - } + case IMGSENSOR_ID_GAMMA_CURVE: + memcpy(control->p_u8, + sp->gamma_curve, + sp->gamma_curve_sz); + break; - buf->length = get_bufsize(&type_inf->fmt[VIDEO_FMT_MAIN]); - buf->m.offset = buf->length * buf->index; + case IMGSENSOR_ID_EXPOSURE: + control->value = sp->ev; + break; - return OK; -} + case IMGSENSOR_ID_HFLIP_VIDEO: + control->value = sp->hflip_video; + break; -static int video_qbuf(FAR struct video_mng_s *vmng, - FAR struct v4l2_buffer *buf) -{ - FAR video_type_inf_t *type_inf; - FAR vbuf_container_t *container; - enum video_state_e next_video_state; - irqstate_t flags; + case IMGSENSOR_ID_VFLIP_VIDEO: + control->value = sp->vflip_video; + break; - if (vmng == NULL || buf == NULL) - { - return -EINVAL; - } + case IMGSENSOR_ID_HFLIP_STILL: + control->value = sp->hflip_still; + break; - type_inf = get_video_type_inf(vmng, buf->type); - if (type_inf == NULL) - { - return -EINVAL; - } + case IMGSENSOR_ID_VFLIP_STILL: + control->value = sp->vflip_still; + break; - if (!is_bufsize_sufficient(vmng, buf->length)) - { - return -EINVAL; - } + case IMGSENSOR_ID_SHARPNESS: + control->value = sp->sharpness; + break; - container = video_framebuff_get_container(&type_inf->bufinf); - if (container == NULL) - { - return -ENOMEM; - } + case IMGSENSOR_ID_COLOR_KILLER: + control->value = sp->colorfx == V4L2_COLORFX_BW; + break; - memcpy(&container->buf, buf, sizeof(struct v4l2_buffer)); - if (buf->memory == V4L2_MEMORY_MMAP) - { - /* only use userptr inside the container */ + case IMGSENSOR_ID_COLORFX: + control->value = sp->colorfx; + break; - container->buf.length = get_bufsize(&type_inf->fmt[VIDEO_FMT_MAIN]); - container->buf.m.userptr = (unsigned long)(type_inf->bufheap + - container->buf.length * buf->index); - } + case IMGSENSOR_ID_AUTOBRIGHTNESS: + control->value = sp->auto_brightness; + break; - video_framebuff_queue_container(&type_inf->bufinf, container); + case IMGSENSOR_ID_ROTATE: + control->value = sp->rotate; + break; - nxmutex_lock(&type_inf->lock_state); - flags = enter_critical_section(); - if (type_inf->state == VIDEO_STATE_STREAMON) - { - leave_critical_section(flags); + case IMGSENSOR_ID_EXPOSURE_AUTO: + control->value = sp->ae; + break; - if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - { - nxmutex_lock(&vmng->still_inf.lock_state); - next_video_state = - estimate_next_video_state(vmng, CAUSE_VIDEO_START); - change_video_state(vmng, next_video_state); - nxmutex_unlock(&vmng->still_inf.lock_state); - } - else - { - container = - video_framebuff_get_vacant_container(&type_inf->bufinf); - if (container != NULL) - { - type_inf->seqnum = 0; - start_capture(vmng, - buf->type, - type_inf->nr_fmt, - type_inf->fmt, - &type_inf->clip, - &type_inf->frame_interval, - container->buf.m.userptr, - container->buf.length); - type_inf->state = VIDEO_STATE_CAPTURE; - } - } - } - else - { - leave_critical_section(flags); - } + case IMGSENSOR_ID_EXPOSURE_ABSOLUTE: + control->value = sp->exposure_time; + break; - nxmutex_unlock(&type_inf->lock_state); - return OK; -} + case IMGSENSOR_ID_FOCUS_ABSOLUTE: + control->value = sp->focus; + break; -static int video_dqbuf(FAR struct video_mng_s *vmng, - FAR struct v4l2_buffer *buf, - int oflags) -{ - irqstate_t flags; - FAR video_type_inf_t *type_inf; - FAR vbuf_container_t *container; - FAR sem_t *dqbuf_wait_flg; - enum video_state_e next_video_state; + case IMGSENSOR_ID_FOCUS_AUTO: + control->value = sp->af; + break; - if (vmng == NULL || buf == NULL) - { - return -EINVAL; - } + case IMGSENSOR_ID_ZOOM_ABSOLUTE: + control->value = sp->zoom; + break; - type_inf = get_video_type_inf(vmng, buf->type); - if (type_inf == NULL) - { - return -EINVAL; - } + case IMGSENSOR_ID_IRIS_ABSOLUTE: + control->value = sp->iris; + break; - container = video_framebuff_dq_valid_container(&type_inf->bufinf); - if (container == NULL) - { - if (oflags & O_NONBLOCK) - { - return -EAGAIN; - } + case IMGSENSOR_ID_AUTO_N_PRESET_WB: + control->value = sp->wb; + break; - /* Not yet done capture. Wait done */ + case IMGSENSOR_ID_WIDE_DYNAMIC_RANGE: + control->value = sp->wdr; + break; - dqbuf_wait_flg = &type_inf->wait_capture.dqbuf_wait_flg; + case IMGSENSOR_ID_IMG_STABILIZATION: + control->value = sp->stabilization; + break; - /* Loop until semaphore is unlocked by capture done or DQCANCEL */ + case IMGSENSOR_ID_ISO_SENSITIVITY: + control->value = sp->iso; + break; - do - { - if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - { - /* If start capture condition is satisfied, start capture */ + case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO: + control->value = sp->iso_auto; + break; - flags = enter_critical_section(); - next_video_state = - estimate_next_video_state(vmng, CAUSE_VIDEO_DQBUF); - change_video_state(vmng, next_video_state); - leave_critical_section(flags); - } + case IMGSENSOR_ID_EXPOSURE_METERING: + control->value = sp->meter; + break; - nxsem_wait_uninterruptible(dqbuf_wait_flg); - } - while (type_inf->wait_capture.waitend_cause == - VIDEO_WAITEND_CAUSE_STILLSTOP); + case IMGSENSOR_ID_SPOT_POSITION: + control->value = sp->spot_pos; + break; - container = type_inf->wait_capture.done_container; - if (container == NULL) - { - /* Waking up without captured data means abort. - * Therefore, Check cause. - */ + case IMGSENSOR_ID_3A_LOCK: + control->value = sp->threea_lock; + break; - if (type_inf->wait_capture.waitend_cause == - VIDEO_WAITEND_CAUSE_DQCANCEL) - { - return -ECANCELED; - } - } + case IMGSENSOR_ID_FLASH_LED_MODE: + control->value = sp->led; + break; - type_inf->wait_capture.done_container = NULL; - } + case IMGSENSOR_ID_JPEG_QUALITY: + control->value = sp->jpeg_quality; + break; - memcpy(buf, &container->buf, sizeof(struct v4l2_buffer)); - video_framebuff_free_container(&type_inf->bufinf, container); + default: + ret = -EINVAL; + break; + } - return OK; + return ret; } -static int video_cancel_dqbuf(FAR struct video_mng_s *vmng, - enum v4l2_buf_type type) +static int check_range(int64_t value, + int64_t min, + int64_t max, + uint64_t step) { - FAR video_type_inf_t *type_inf; - - type_inf = get_video_type_inf(vmng, type); - if (type_inf == NULL) + if (value < min || value > max || + (value - min) % step != 0) { return -EINVAL; } - if (!is_sem_waited(&type_inf->wait_capture.dqbuf_wait_flg)) - { - /* In not waiting DQBUF case, return OK */ - - return OK; - } - - type_inf->wait_capture.waitend_cause = VIDEO_WAITEND_CAUSE_DQCANCEL; - - /* If capture is done before nxsem_post, cause is overwritten */ - - return nxsem_post(&type_inf->wait_capture.dqbuf_wait_flg); -} - -static bool validate_clip_range(int32_t pos, uint32_t c_sz, uint16_t frm_sz) -{ - return pos >= 0 && c_sz <= frm_sz && pos + c_sz <= frm_sz; -} - -static bool validate_clip_setting(FAR struct v4l2_rect *clip, - FAR video_format_t *fmt) -{ - DEBUGASSERT(clip && fmt); - - /* Not permit the setting which do not fit inside frame size. */ - - return validate_clip_range(clip->left, clip->width, fmt->width) && - validate_clip_range(clip->top, clip->height, fmt->height); + return OK; } -static int video_s_selection(FAR struct video_mng_s *vmng, - FAR struct v4l2_selection *clip) +static int save_scene_param(FAR capture_mng_t *cmng, + enum v4l2_scene_mode mode, + uint32_t id, + FAR struct v4l2_ext_control *control) { - FAR video_type_inf_t *type_inf; - uint32_t p_u32[IMGSENSOR_CLIP_NELEM]; - imgsensor_value_t val; - int32_t id; + imgsensor_supported_value_t value; + FAR imgsensor_capability_range_t *range = &value.u.range; + FAR imgsensor_capability_discrete_t *disc = &value.u.discrete; + FAR imgsensor_capability_elems_t *elem = &value.u.elems; + FAR capture_scene_params_t *sp; int ret; + int i; - ASSERT(vmng && vmng->imgsensor); + ASSERT(cmng->imgsensor); - if (clip == NULL) + sp = search_scene_param(cmng, mode); + if (sp == NULL) { - return -EINVAL; - } + /* Unsupported scene mode */ - type_inf = get_video_type_inf(vmng, clip->type); - if (type_inf == NULL) - { return -EINVAL; } - if (type_inf->state != VIDEO_STATE_STREAMOFF) - { - return -EBUSY; - } - - if (!validate_clip_setting(&clip->r, type_inf->fmt)) + ret = IMGSENSOR_GET_SUPPORTED_VALUE(cmng->imgsensor, id, &value); + if (ret < 0) { - return -EINVAL; - } + /* Unsupported camera parameter */ - ret = validate_frame_setting(vmng, - clip->type, - type_inf->nr_fmt, - type_inf->fmt, - &clip->r, - &type_inf->frame_interval); - if (ret != OK) - { return ret; } - id = clip->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? - IMGSENSOR_ID_CLIP_VIDEO : IMGSENSOR_ID_CLIP_STILL; - - p_u32[IMGSENSOR_CLIP_INDEX_LEFT] = clip->r.left; - p_u32[IMGSENSOR_CLIP_INDEX_TOP] = clip->r.top; - p_u32[IMGSENSOR_CLIP_INDEX_WIDTH] = clip->r.width; - p_u32[IMGSENSOR_CLIP_INDEX_HEIGHT] = clip->r.height; - - val.p_u32 = p_u32; - ret = IMGSENSOR_SET_VALUE(vmng->imgsensor, id, sizeof(p_u32), val); - if (ret != OK) + switch (value.type) { - return ret; - } - - memcpy(&type_inf->clip, &clip->r, sizeof(struct v4l2_rect)); - return ret; -} - -static int video_g_selection(FAR struct video_mng_s *vmng, - FAR struct v4l2_selection *clip) -{ - FAR video_type_inf_t *type_inf; + case IMGSENSOR_CTRL_TYPE_INTEGER_MENU: + for (i = 0; i < disc->nr_values; i++) + { + if (control->value == disc->values[i]) + { + break; + } + } - ASSERT(vmng); + if (i >= disc->nr_values) + { + return -EINVAL; + } - if (clip == NULL) - { - return -EINVAL; - } + break; - type_inf = get_video_type_inf(vmng, clip->type); - if (type_inf == NULL) - { - return -EINVAL; - } + case IMGSENSOR_CTRL_TYPE_U8: + if (control->size < elem->nr_elems * sizeof(uint8_t)) + { + return -EINVAL; + } - memcpy(&clip->r, &type_inf->clip, sizeof(struct v4l2_rect)); - return OK; -} + for (i = 0; i < elem->nr_elems; i++) + { + ret = check_range(control->p_u8[i], + elem->minimum, + elem->maximum, + elem->step); + if (ret != OK) + { + return ret; + } + } -static int validate_frame_setting(FAR video_mng_t *vmng, - enum v4l2_buf_type type, - uint8_t nr_fmt, - FAR video_format_t *vfmt, - FAR struct v4l2_rect *clip, - FAR struct v4l2_fract *interval) -{ - video_format_t c_fmt[MAX_VIDEO_FMT]; - imgdata_format_t df[MAX_VIDEO_FMT]; - imgsensor_format_t sf[MAX_VIDEO_FMT]; - imgdata_interval_t di; - imgsensor_interval_t si; - int ret; + break; - ASSERT(vfmt && interval && vmng->imgsensor && vmng->imgdata); + case IMGSENSOR_CTRL_TYPE_U16: + if (control->size < elem->nr_elems * sizeof(uint16_t)) + { + return -EINVAL; + } - /* Return OK only in case both image data driver and - * image sensor driver support. - */ + for (i = 0; i < elem->nr_elems; i++) + { + ret = check_range(control->p_u16[i], + elem->minimum, + elem->maximum, + elem->step); + if (ret != OK) + { + return ret; + } + } - get_clipped_format(nr_fmt, vfmt, clip, c_fmt); + break; - convert_to_imgdatafmt(&c_fmt[VIDEO_FMT_MAIN], &df[IMGDATA_FMT_MAIN]); - convert_to_imgdatafmt(&c_fmt[VIDEO_FMT_SUB], &df[IMGDATA_FMT_SUB]); - convert_to_imgdatainterval(interval, &di); - convert_to_imgsensorfmt(&vfmt[VIDEO_FMT_MAIN], &sf[IMGSENSOR_FMT_MAIN]); - convert_to_imgsensorfmt(&vfmt[VIDEO_FMT_SUB], &sf[IMGSENSOR_FMT_SUB]); - convert_to_imgsensorinterval(interval, &si); + case IMGSENSOR_CTRL_TYPE_U32: + if (control->size < elem->nr_elems * sizeof(uint32_t)) + { + return -EINVAL; + } - ret = IMGSENSOR_VALIDATE_FRAME_SETTING(vmng->imgsensor, - type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? - IMGSENSOR_STREAM_TYPE_VIDEO : IMGSENSOR_STREAM_TYPE_STILL, - nr_fmt, sf, &si); - if (ret != OK) - { - return ret; - } + for (i = 0; i < elem->nr_elems; i++) + { + ret = check_range(control->p_u32[i], + elem->minimum, + elem->maximum, + elem->step); + if (ret != OK) + { + return ret; + } + } - return IMGDATA_VALIDATE_FRAME_SETTING(vmng->imgdata, nr_fmt, df, &di); -} + break; -static size_t get_bufsize(FAR video_format_t *vf) -{ - size_t ret = vf->width * vf->height; - switch (vf->pixelformat) - { - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_YUV420: - return ret * 3 / 2; - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_UYVY: - case V4L2_PIX_FMT_RGB565: - case V4L2_PIX_FMT_JPEG: default: - return ret * 2; + ret = check_range(control->value, + range->minimum, + range->maximum, + range->step); + if (ret != OK) + { + return ret; + } + + break; } -} -static size_t get_heapsize(FAR video_type_inf_t *type_inf) -{ - return type_inf->bufinf.container_size * - get_bufsize(&type_inf->fmt[VIDEO_FMT_MAIN]); -} + switch (id) + { + case IMGSENSOR_ID_BRIGHTNESS: + sp->brightness = control->value; + break; -static int video_try_fmt(FAR struct video_mng_s *priv, - FAR struct v4l2_format *v4l2) -{ - FAR video_type_inf_t *type_inf; - video_format_t vf[MAX_VIDEO_FMT]; - uint8_t nr_fmt; + case IMGSENSOR_ID_CONTRAST: + sp->contrast = control->value; + break; - ASSERT(priv && priv->imgsensor && priv->imgdata); + case IMGSENSOR_ID_SATURATION: + sp->saturation = control->value; + break; - if (v4l2 == NULL) - { - return -EINVAL; - } + case IMGSENSOR_ID_HUE: + sp->hue = control->value; + break; - type_inf = get_video_type_inf(priv, v4l2->type); - if (type_inf == NULL) - { - return -EINVAL; - } - - switch (v4l2->fmt.pix.pixelformat) - { - case V4L2_PIX_FMT_SUBIMG_UYVY: - case V4L2_PIX_FMT_SUBIMG_RGB565: - if (type_inf->fmt[VIDEO_FMT_MAIN].pixelformat != - V4L2_PIX_FMT_JPEG_WITH_SUBIMG) - { - return -EPERM; - } - - /* Validate both main image and subimage. */ + case IMGSENSOR_ID_AUTO_WHITE_BALANCE: + sp->awb = control->value; + break; - nr_fmt = 2; - memcpy(&vf[VIDEO_FMT_MAIN], - &type_inf->fmt[VIDEO_FMT_MAIN], - sizeof(video_format_t)); - vf[VIDEO_FMT_SUB].width = v4l2->fmt.pix.width; - vf[VIDEO_FMT_SUB].height = v4l2->fmt.pix.height; - vf[VIDEO_FMT_SUB].pixelformat = - v4l2->fmt.pix.pixelformat == V4L2_PIX_FMT_SUBIMG_UYVY ? - V4L2_PIX_FMT_UYVY : V4L2_PIX_FMT_RGB565; + case IMGSENSOR_ID_RED_BALANCE: + sp->red = control->value; break; - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_UYVY: - case V4L2_PIX_FMT_RGB565: - case V4L2_PIX_FMT_JPEG: - case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: - nr_fmt = 1; - vf[VIDEO_FMT_MAIN].width = v4l2->fmt.pix.width; - vf[VIDEO_FMT_MAIN].height = v4l2->fmt.pix.height; - vf[VIDEO_FMT_MAIN].pixelformat = v4l2->fmt.pix.pixelformat; + + case IMGSENSOR_ID_BLUE_BALANCE: + sp->blue = control->value; break; - default: - return -EINVAL; - } + case IMGSENSOR_ID_GAMMA: + sp->gamma = control->value; + break; - return validate_frame_setting(priv, - v4l2->type, - nr_fmt, - vf, - &type_inf->clip, - &type_inf->frame_interval); -} + case IMGSENSOR_ID_GAMMA_CURVE: + memcpy(sp->gamma_curve, + control->p_u8, + sp->gamma_curve_sz); + break; -static int video_g_fmt(FAR struct video_mng_s *priv, - FAR struct v4l2_format *fmt) -{ - FAR video_type_inf_t *type_inf; + case IMGSENSOR_ID_EXPOSURE: + sp->ev = control->value; + break; - type_inf = get_video_type_inf(priv, fmt->type); - if (type_inf == NULL) - { - return -EINVAL; - } + case IMGSENSOR_ID_HFLIP_VIDEO: + sp->hflip_video = control->value; + break; - memset(&fmt->fmt, 0, sizeof(fmt->fmt)); - fmt->fmt.pix.width = type_inf->fmt[VIDEO_FMT_MAIN].width; - fmt->fmt.pix.height = type_inf->fmt[VIDEO_FMT_MAIN].height; - fmt->fmt.pix.pixelformat = type_inf->fmt[VIDEO_FMT_MAIN].pixelformat; + case IMGSENSOR_ID_VFLIP_VIDEO: + sp->vflip_video = control->value; + break; - return OK; -} + case IMGSENSOR_ID_HFLIP_STILL: + sp->hflip_still = control->value; + break; -static int video_s_fmt(FAR struct video_mng_s *priv, - FAR struct v4l2_format *fmt) -{ - FAR video_type_inf_t *type_inf; - int ret; + case IMGSENSOR_ID_VFLIP_STILL: + sp->vflip_still = control->value; + break; - ret = video_try_fmt(priv, fmt); - if (ret != 0) - { - return ret; - } + case IMGSENSOR_ID_SHARPNESS: + sp->sharpness = control->value; + break; - type_inf = get_video_type_inf(priv, fmt->type); - if (type_inf == NULL) - { - return -EINVAL; - } + case IMGSENSOR_ID_COLOR_KILLER: + sp->colorfx = control->value ? V4L2_COLORFX_BW : V4L2_COLORFX_NONE; + break; - if (type_inf->state != VIDEO_STATE_STREAMOFF) - { - return -EBUSY; - } + case IMGSENSOR_ID_COLORFX: + sp->colorfx = control->value; + break; - switch (fmt->fmt.pix.pixelformat) - { - case V4L2_PIX_FMT_SUBIMG_UYVY: - case V4L2_PIX_FMT_SUBIMG_RGB565: - if (type_inf->fmt[VIDEO_FMT_MAIN].pixelformat != - V4L2_PIX_FMT_JPEG_WITH_SUBIMG) - { - return -EPERM; - } + case IMGSENSOR_ID_AUTOBRIGHTNESS: + sp->auto_brightness = control->value; + break; - type_inf->fmt[VIDEO_FMT_SUB].width = fmt->fmt.pix.width; - type_inf->fmt[VIDEO_FMT_SUB].height = fmt->fmt.pix.height; - type_inf->fmt[VIDEO_FMT_SUB].pixelformat = - fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_SUBIMG_UYVY ? - V4L2_PIX_FMT_UYVY : V4L2_PIX_FMT_RGB565; - type_inf->nr_fmt = 2; + case IMGSENSOR_ID_ROTATE: + sp->rotate = control->value; break; - default: - type_inf->fmt[VIDEO_FMT_MAIN].width = fmt->fmt.pix.width; - type_inf->fmt[VIDEO_FMT_MAIN].height = fmt->fmt.pix.height; - type_inf->fmt[VIDEO_FMT_MAIN].pixelformat = fmt->fmt.pix.pixelformat; - type_inf->nr_fmt = 1; + case IMGSENSOR_ID_EXPOSURE_AUTO: + sp->ae = control->value; break; - } - return OK; -} + case IMGSENSOR_ID_EXPOSURE_ABSOLUTE: + sp->exposure_time = control->value; + break; -static int video_s_parm(FAR struct video_mng_s *priv, - FAR struct v4l2_streamparm *parm) -{ - FAR video_type_inf_t *type_inf; - int ret; + case IMGSENSOR_ID_FOCUS_ABSOLUTE: + sp->focus = control->value; + break; - ASSERT(priv->imgsensor && priv->imgdata); + case IMGSENSOR_ID_FOCUS_AUTO: + sp->af = control->value; + break; - type_inf = get_video_type_inf(priv, parm->type); - if (type_inf == NULL) - { - return -EINVAL; - } + case IMGSENSOR_ID_ZOOM_ABSOLUTE: + sp->zoom = control->value; + break; - if (type_inf->state != VIDEO_STATE_STREAMOFF) - { - return -EBUSY; - } + case IMGSENSOR_ID_IRIS_ABSOLUTE: + sp->iris = control->value; + break; - ret = validate_frame_setting(priv, - parm->type, - type_inf->nr_fmt, - type_inf->fmt, - &type_inf->clip, - &parm->parm.capture.timeperframe); - if (ret != OK) - { - return ret; - } + case IMGSENSOR_ID_AUTO_N_PRESET_WB: + sp->wb = control->value; + break; - memcpy(&type_inf->frame_interval, - &parm->parm.capture.timeperframe, - sizeof(struct v4l2_fract)); + case IMGSENSOR_ID_WIDE_DYNAMIC_RANGE: + sp->wdr = control->value; + break; - return ret; -} + case IMGSENSOR_ID_IMG_STABILIZATION: + sp->stabilization = control->value; + break; -static int video_g_parm(FAR struct video_mng_s *vmng, - FAR struct v4l2_streamparm *parm) -{ - FAR video_type_inf_t *type_inf; - int ret = -EINVAL; + case IMGSENSOR_ID_ISO_SENSITIVITY: + sp->iso = control->value; + break; - DEBUGASSERT(vmng && vmng->imgsensor); + case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO: + sp->iso_auto = control->value; + break; - type_inf = get_video_type_inf(vmng, parm->type); - if (type_inf == NULL) - { - return -EINVAL; - } + case IMGSENSOR_ID_EXPOSURE_METERING: + sp->meter = control->value; + break; - memset(&parm->parm, 0, sizeof(parm->parm)); + case IMGSENSOR_ID_SPOT_POSITION: + sp->spot_pos = control->value; + break; - if (type_inf->state == VIDEO_STATE_CAPTURE) - { - /* If capture is started and lower driver has the get_frame_interval(), - * query lower driver. - */ + case IMGSENSOR_ID_3A_LOCK: + sp->threea_lock = control->value; + break; - ret = IMGSENSOR_GET_FRAME_INTERVAL(vmng->imgsensor, parm->type, - (imgsensor_interval_t *)&parm->parm.capture.timeperframe); - } + case IMGSENSOR_ID_FLASH_LED_MODE: + sp->led = control->value; + break; - if (ret != OK) - { - /* In no capture state or error case, return stored value. */ + case IMGSENSOR_ID_JPEG_QUALITY: + sp->jpeg_quality = control->value; + break; - memcpy(&parm->parm.capture.timeperframe, - &type_inf->frame_interval, - sizeof(struct v4l2_fract)); + default: + return -EINVAL; } - parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; return OK; } -static int video_streamon(FAR struct video_mng_s *vmng, - FAR enum v4l2_buf_type *type) +/* Callback function which device driver call when capture has done. */ + +static int complete_capture(uint8_t err_code, + uint32_t datasize, + FAR const struct timeval *ts, + FAR void *arg) { - FAR video_type_inf_t *type_inf; - enum video_state_e next_video_state; - int ret = OK; + FAR capture_mng_t *cmng = (FAR capture_mng_t *)arg; + FAR capture_type_inf_t *type_inf; + FAR vbuf_container_t *container = NULL; + enum v4l2_buf_type buf_type; + irqstate_t flags; - if (vmng == NULL || type == NULL) - { - return -EINVAL; - } + flags = enter_critical_section(); - type_inf = get_video_type_inf(vmng, *type); + buf_type = cmng->still_inf.state == CAPTURE_STATE_CAPTURE ? + V4L2_BUF_TYPE_STILL_CAPTURE : V4L2_BUF_TYPE_VIDEO_CAPTURE; + + type_inf = get_capture_type_inf(cmng, buf_type); if (type_inf == NULL) { + leave_critical_section(flags); return -EINVAL; } - if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - { - /* No procedure for VIDIOC_STREAMON(STILL_CAPTURE) */ - - return OK; - } - - nxmutex_lock(&type_inf->lock_state); + poll_notify(&type_inf->fds, 1, POLLIN); - if (type_inf->state != VIDEO_STATE_STREAMOFF) + if (err_code == 0) { - ret = -EPERM; + type_inf->bufinf.vbuf_curr->buf.flags = 0; + if (type_inf->remaining_capnum > 0) + { + type_inf->remaining_capnum--; + } } else { - next_video_state = - estimate_next_video_state(vmng, CAUSE_VIDEO_START); - change_video_state(vmng, next_video_state); + type_inf->bufinf.vbuf_curr->buf.flags = V4L2_BUF_FLAG_ERROR; } - nxmutex_unlock(&type_inf->lock_state); - return ret; -} - -static int video_streamoff(FAR struct video_mng_s *vmng, - FAR enum v4l2_buf_type *type) -{ - FAR video_type_inf_t *type_inf; - enum video_state_e next_video_state; - irqstate_t flags; - int ret = OK; - - if (vmng == NULL || type == NULL) + type_inf->bufinf.vbuf_curr->buf.bytesused = datasize; + if (ts != NULL) { - return -EINVAL; + type_inf->bufinf.vbuf_curr->buf.timestamp = *ts; } - type_inf = get_video_type_inf(vmng, *type); - if (type_inf == NULL) - { - return -EINVAL; - } + video_framebuff_capture_done(&type_inf->bufinf); - if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (is_sem_waited(&type_inf->wait_capture.dqbuf_wait_flg)) { - /* No procedure for VIDIOC_STREAMOFF(STILL_CAPTURE) */ + /* If waiting capture in DQBUF, + * get/save container and unlock wait + */ - return OK; + type_inf->wait_capture.done_container = + video_framebuff_pop_curr_container(&type_inf->bufinf); + type_inf->wait_capture.waitend_cause = WAITEND_CAUSE_CAPTUREDONE; + nxsem_post(&type_inf->wait_capture.dqbuf_wait_flg); } - flags = enter_critical_section(); - - if (type_inf->state == VIDEO_STATE_STREAMOFF) + if (type_inf->remaining_capnum == 0) { - ret = -EPERM; + stop_capture(cmng, buf_type); + type_inf->state = CAPTURE_STATE_STREAMOFF; + + /* If stop still stream, notify it to video stream */ + + if (buf_type == V4L2_BUF_TYPE_STILL_CAPTURE && + is_sem_waited(&cmng->capture_inf.wait_capture.dqbuf_wait_flg)) + { + cmng->capture_inf.wait_capture.waitend_cause = + WAITEND_CAUSE_STILLSTOP; + nxsem_post(&cmng->capture_inf.wait_capture.dqbuf_wait_flg); + } } else { - next_video_state = - estimate_next_video_state(vmng, CAUSE_VIDEO_STOP); - change_video_state(vmng, next_video_state); + container = video_framebuff_get_vacant_container(&type_inf->bufinf); + if (container == NULL) + { + stop_capture(cmng, buf_type); + type_inf->state = CAPTURE_STATE_STREAMON; + } + else + { + IMGDATA_SET_BUF(cmng->imgdata, + (FAR uint8_t *)container->buf.m.userptr, + container->buf.length); + container->buf.sequence = type_inf->seqnum++; + } } leave_critical_section(flags); - - return ret; + return OK; } -static int video_do_halfpush(FAR struct video_mng_s *priv, bool enable) +static FAR struct imgsensor_s * +get_connected_imgsensor(FAR struct imgsensor_s **sensors, + size_t sensor_num) { - struct v4l2_ext_controls ext_controls; - struct v4l2_ext_control control[2]; - - /* Replace to VIDIOC_S_EXT_CTRLS format */ - - control[0].id = V4L2_CID_3A_LOCK; - control[0].value = enable ? - V4L2_LOCK_EXPOSURE | V4L2_LOCK_WHITE_BALANCE : 0; - control[1].id = V4L2_CID_AUTO_FOCUS_START; - control[1].value = enable ? true : false; - - ext_controls.ctrl_class = V4L2_CTRL_CLASS_CAMERA; - ext_controls.count = 2; - ext_controls.controls = control; + FAR struct imgsensor_s *sensor = NULL; + int i; - /* Execute VIDIOC_S_EXT_CTRLS */ + for (i = 0; i < sensor_num; i++) + { + if (sensors[i] && + IMGSENSOR_IS_AVAILABLE(sensors[i])) + { + sensor = sensors[i]; + break; + } + } - return video_s_ext_ctrls(priv, &ext_controls); + return sensor; } -static int video_takepict_start(FAR struct video_mng_s *vmng, - int32_t capture_num) +/**************************************************************************** + * Ioctl Functions + ****************************************************************************/ + +static int capture_querycap(FAR struct v4l2_s *v4l2, + FAR struct v4l2_capability *cap) { - enum video_state_e next_video_state; - FAR vbuf_container_t *container; - irqstate_t flags; - int ret = OK; + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR const char *name; - if (vmng == NULL) + if (cmng == NULL || cap == NULL) { return -EINVAL; } - nxmutex_lock(&vmng->still_inf.lock_state); + ASSERT(cmng->imgsensor); - if (vmng->still_inf.state != VIDEO_STATE_STREAMOFF) + name = IMGSENSOR_GET_DRIVER_NAME(cmng->imgsensor); + if (name == NULL) { - ret = -EPERM; + return -ENOTTY; } - else - { - if (capture_num > 0) - { - vmng->still_inf.remaining_capnum = capture_num; - } - else - { - vmng->still_inf.remaining_capnum = VIDEO_REMAINING_CAPNUM_INFINITY; - } - /* Control video stream prior to still stream */ + memset(cap, 0, sizeof(struct v4l2_capability)); - flags = enter_critical_section(); + /* cap->driver needs to be NULL-terminated. */ - next_video_state = estimate_next_video_state(vmng, - CAUSE_STILL_START); - change_video_state(vmng, next_video_state); + strlcpy((FAR char *)cap->driver, name, sizeof(cap->driver)); + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - leave_critical_section(flags); + return OK; +} - container = - video_framebuff_get_vacant_container(&vmng->still_inf.bufinf); - if (container != NULL) - { - /* Start still stream capture */ +static int capture_g_input(FAR int *num) +{ + *num = 0; + return OK; +} - start_capture(vmng, - V4L2_BUF_TYPE_STILL_CAPTURE, - vmng->still_inf.nr_fmt, - vmng->still_inf.fmt, - &vmng->still_inf.clip, - &vmng->still_inf.frame_interval, - container->buf.m.userptr, - container->buf.length); +static int capture_enum_input(FAR struct v4l2_s *v4l2, + FAR struct v4l2_input *input) +{ + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR const char *name; - vmng->still_inf.state = VIDEO_STATE_CAPTURE; - } - else - { - vmng->still_inf.state = VIDEO_STATE_STREAMON; - } + if (cmng == NULL || input->index > 0) + { + return -EINVAL; } - nxmutex_unlock(&vmng->still_inf.lock_state); - return ret; + ASSERT(cmng->imgsensor); + + name = IMGSENSOR_GET_DRIVER_NAME(cmng->imgsensor); + if (name == NULL) + { + return -ENOTTY; + } + + memset(input, 0, sizeof(struct v4l2_input)); + strlcpy((FAR char *)input->name, name, sizeof(input->name)); + input->type = V4L2_INPUT_TYPE_CAMERA; + + return OK; } -static int video_takepict_stop(FAR struct video_mng_s *vmng, bool halfpush) +static int capture_reqbufs(FAR struct v4l2_s *v4l2, + FAR struct v4l2_requestbuffers *reqbufs) { - enum video_state_e next_video_state; + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; irqstate_t flags; int ret = OK; - if (vmng == NULL) + if (cmng == NULL || reqbufs == NULL) + { + return -EINVAL; + } + + type_inf = get_capture_type_inf(cmng, reqbufs->type); + if (type_inf == NULL) { return -EINVAL; } - nxmutex_lock(&vmng->still_inf.lock_state); + flags = enter_critical_section(); - if (vmng->still_inf.state == VIDEO_STATE_STREAMOFF && - vmng->still_inf.remaining_capnum == VIDEO_REMAINING_CAPNUM_INFINITY) + if (type_inf->state == CAPTURE_STATE_CAPTURE) { + /* In capture, REQBUFS is not permitted */ + ret = -EPERM; } else { - flags = enter_critical_section(); - if (vmng->still_inf.state == VIDEO_STATE_CAPTURE) + if (reqbufs->count > V4L2_REQBUFS_COUNT_MAX) { - stop_capture(vmng, V4L2_BUF_TYPE_STILL_CAPTURE); + reqbufs->count = V4L2_REQBUFS_COUNT_MAX; } - leave_critical_section(flags); - - vmng->still_inf.state = VIDEO_STATE_STREAMOFF; - vmng->still_inf.remaining_capnum = VIDEO_REMAINING_CAPNUM_INFINITY; - - /* Control video stream */ + video_framebuff_change_mode(&type_inf->bufinf, reqbufs->mode); + ret = video_framebuff_realloc_container(&type_inf->bufinf, + reqbufs->count); + if (ret == OK && reqbufs->memory == V4L2_MEMORY_MMAP) + { + if (type_inf->bufheap != NULL) + { + kumm_free(type_inf->bufheap); + } - nxmutex_lock(&vmng->video_inf.lock_state); - next_video_state = estimate_next_video_state(vmng, - CAUSE_STILL_STOP); - change_video_state(vmng, next_video_state); - nxmutex_unlock(&vmng->video_inf.lock_state); + type_inf->bufheap = kumm_memalign(32, + reqbufs->count * get_bufsize(&type_inf->fmt[CAPTURE_FMT_MAIN])); + if (type_inf->bufheap == NULL) + { + ret = -ENOMEM; + } + } } - nxmutex_unlock(&vmng->still_inf.lock_state); + leave_critical_section(flags); return ret; } -static int video_queryctrl(FAR video_mng_t *vmng, - FAR struct v4l2_queryctrl *ctrl) +static int capture_querybuf(FAR struct v4l2_s *v4l2, + FAR struct v4l2_buffer *buf) { - struct v4l2_query_ext_ctrl ext_ctrl; - int ret; + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; - if (ctrl == NULL) + if (cmng == NULL || buf == NULL || buf->memory != V4L2_MEMORY_MMAP) { return -EINVAL; } - /* Replace to VIDIOC_QUERY_EXT_CTRL format */ - - ext_ctrl.ctrl_class = ctrl->ctrl_class; - ext_ctrl.id = ctrl->id; - - ret = video_query_ext_ctrl(vmng, &ext_ctrl); - if (ret != OK) + type_inf = get_capture_type_inf(cmng, buf->type); + if (type_inf == NULL) { - return ret; + return -EINVAL; } - if (ext_ctrl.type == V4L2_CTRL_TYPE_INTEGER64 || - ext_ctrl.type == V4L2_CTRL_TYPE_U8 || - ext_ctrl.type == V4L2_CTRL_TYPE_U16 || - ext_ctrl.type == V4L2_CTRL_TYPE_U32) + if (buf->index >= type_inf->bufinf.container_size) { - /* Unsupported type in VIDIOC_QUERYCTRL */ - return -EINVAL; } - /* Replace gotten value to VIDIOC_QUERYCTRL */ - - ctrl->type = ext_ctrl.type; - ctrl->minimum = ext_ctrl.minimum; - ctrl->maximum = ext_ctrl.maximum; - ctrl->step = ext_ctrl.step; - ctrl->default_value = ext_ctrl.default_value; - ctrl->flags = ext_ctrl.flags; - strlcpy(ctrl->name, ext_ctrl.name, sizeof(ctrl->name)); + buf->length = get_bufsize(&type_inf->fmt[CAPTURE_FMT_MAIN]); + buf->m.offset = buf->length * buf->index; return OK; } -static void set_parameter_name(uint32_t id, char *name) +static int capture_qbuf(FAR struct v4l2_s *v4l2, + FAR struct v4l2_buffer *buf) { - int size = - sizeof(g_video_parameter_name) / sizeof(video_parameter_name_t); - int cnt; + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; + FAR vbuf_container_t *container; + enum capture_state_e next_capture_state; + irqstate_t flags; - for (cnt = 0; cnt < size; cnt++) + if (cmng == NULL || buf == NULL) { - if (g_video_parameter_name[cnt].id == id) - { - break; - } + return -EINVAL; } - ASSERT(cnt < size); - - /* copy size = 32 is due to V4L2 specification. */ - - strlcpy(name, g_video_parameter_name[cnt].name, 32); -} - -static int video_query_ext_ctrl(FAR struct video_mng_s *vmng, - FAR struct v4l2_query_ext_ctrl *attr) -{ - imgsensor_supported_value_t value; - imgsensor_capability_range_t *range = &value.u.range; - imgsensor_capability_discrete_t *disc = &value.u.discrete; - imgsensor_capability_elems_t *elem = &value.u.elems; - int ret; - - ASSERT(vmng->imgsensor); + type_inf = get_capture_type_inf(cmng, buf->type); + if (type_inf == NULL) + { + return -EINVAL; + } - if (attr == NULL) + if (!is_bufsize_sufficient(cmng, buf->length)) { return -EINVAL; } - attr->flags = 0; - attr->elem_size = 0; - attr->nr_of_dims = 0; - memset(attr->dims, 0, sizeof(attr->dims)); + container = video_framebuff_get_container(&type_inf->bufinf); + if (container == NULL) + { + return -ENOMEM; + } - if (attr->ctrl_class == V4L2_CTRL_CLASS_CAMERA && - attr->id == V4L2_CID_SCENE_MODE) + memcpy(&container->buf, buf, sizeof(struct v4l2_buffer)); + if (buf->memory == V4L2_MEMORY_MMAP) { - /* Scene mode is processed in only video driver. */ + /* only use userptr inside the container */ - attr->type = V4L2_CTRL_TYPE_INTEGER_MENU; - attr->minimum = 0; - attr->maximum = vmng->video_scence_num - 1; - attr->step = 1; - attr->default_value = 0; - attr->flags = 0; - strlcpy(attr->name, "Scene Mode", 32); + container->buf.length = get_bufsize(&type_inf->fmt[CAPTURE_FMT_MAIN]); + container->buf.m.userptr = (unsigned long)(type_inf->bufheap + + container->buf.length * buf->index); } - else + + video_framebuff_queue_container(&type_inf->bufinf, container); + + nxmutex_lock(&type_inf->lock_state); + flags = enter_critical_section(); + if (type_inf->state == CAPTURE_STATE_STREAMON) { - ret = IMGSENSOR_GET_SUPPORTED_VALUE(vmng->imgsensor, - VIDEO_ID(attr->ctrl_class, attr->id), - &value); - if (ret < 0) + leave_critical_section(flags); + + if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - return ret; + nxmutex_lock(&cmng->still_inf.lock_state); + next_capture_state = + estimate_next_capture_state(cmng, CAUSE_CAPTURE_START); + change_capture_state(cmng, next_capture_state); + nxmutex_unlock(&cmng->still_inf.lock_state); } - - attr->type = value.type; - attr->flags = 0; - - switch (value.type) + else { - case IMGSENSOR_CTRL_TYPE_INTEGER_MENU: - attr->minimum = 0; - attr->maximum = disc->nr_values - 1; - attr->step = 1; - attr->default_value = disc->default_value; - break; - - case IMGSENSOR_CTRL_TYPE_U8: - case IMGSENSOR_CTRL_TYPE_U16: - case IMGSENSOR_CTRL_TYPE_U32: - attr->minimum = elem->minimum; - attr->maximum = elem->maximum; - attr->step = elem->step; - attr->elems = elem->nr_elems; - break; - - default: - attr->minimum = range->minimum; - attr->maximum = range->maximum; - attr->step = range->step; - attr->default_value = range->default_value; - break; + container = + video_framebuff_get_vacant_container(&type_inf->bufinf); + if (container != NULL) + { + type_inf->seqnum = 0; + start_capture(cmng, + buf->type, + type_inf->nr_fmt, + type_inf->fmt, + &type_inf->clip, + &type_inf->frame_interval, + container->buf.m.userptr, + container->buf.length); + type_inf->state = CAPTURE_STATE_CAPTURE; + } } - - set_parameter_name(VIDEO_ID(attr->ctrl_class, attr->id), - attr->name); + } + else + { + leave_critical_section(flags); } + nxmutex_unlock(&type_inf->lock_state); return OK; } -static int video_querymenu(FAR video_mng_t *vmng, - FAR struct v4l2_querymenu *menu) +static int capture_dqbuf(FAR struct v4l2_s *v4l2, + FAR struct v4l2_buffer *buf, int oflags) { - imgsensor_supported_value_t value; - int ret; - - ASSERT(vmng->imgsensor); + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; + FAR vbuf_container_t *container; + FAR sem_t *dqbuf_wait_flg; + enum capture_state_e next_capture_state; + irqstate_t flags; - if (menu == NULL) + if (cmng == NULL || buf == NULL) { return -EINVAL; } - if (menu->ctrl_class == V4L2_CTRL_CLASS_CAMERA && - menu->id == V4L2_CID_SCENE_MODE) + type_inf = get_capture_type_inf(cmng, buf->type); + if (type_inf == NULL) { - /* Scene mode is processed in only video driver. */ - - if (menu->index > vmng->video_scence_num - 1) - { - return -EINVAL; - } - - menu->value = vmng->video_scene_param[menu->index]->mode; + return -EINVAL; } - else + + container = video_framebuff_dq_valid_container(&type_inf->bufinf); + if (container == NULL) { - ret = IMGSENSOR_GET_SUPPORTED_VALUE(vmng->imgsensor, - VIDEO_ID(menu->ctrl_class, menu->id), - &value); - if (ret < 0) + if (oflags & O_NONBLOCK) { - return ret; + return -EAGAIN; } - if (value.type != IMGSENSOR_CTRL_TYPE_INTEGER_MENU) + /* Not yet done capture. Wait done */ + + dqbuf_wait_flg = &type_inf->wait_capture.dqbuf_wait_flg; + + /* Loop until semaphore is unlocked by capture done or DQCANCEL */ + + do { - /* VIDIOC_QUERYMENU is used only for - * IMGSENSOR_CTRL_TYPE_INTEGER_MENU. - */ + if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + { + /* If start capture condition is satisfied, start capture */ - return -EINVAL; + flags = enter_critical_section(); + next_capture_state = + estimate_next_capture_state(cmng, CAUSE_CAPTURE_DQBUF); + change_capture_state(cmng, next_capture_state); + leave_critical_section(flags); + } + + nxsem_wait_uninterruptible(dqbuf_wait_flg); } + while (type_inf->wait_capture.waitend_cause == + WAITEND_CAUSE_STILLSTOP); - if (menu->index >= value.u.discrete.nr_values) + container = type_inf->wait_capture.done_container; + if (container == NULL) { - return -EINVAL; + /* Waking up without captured data means abort. + * Therefore, Check cause. + */ + + if (type_inf->wait_capture.waitend_cause == WAITEND_CAUSE_DQCANCEL) + { + return -ECANCELED; + } } - menu->value = value.u.discrete.values[menu->index]; + type_inf->wait_capture.done_container = NULL; } + memcpy(buf, &container->buf, sizeof(struct v4l2_buffer)); + video_framebuff_free_container(&type_inf->bufinf, container); + return OK; } -static int video_g_ctrl(FAR struct video_mng_s *priv, - FAR struct v4l2_control *ctrl) +static int capture_cancel_dqbuf(FAR struct v4l2_s *v4l2, + enum v4l2_buf_type type) { - struct v4l2_ext_controls ext_controls; - struct v4l2_ext_control control; - int ret; + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; - memset(&ext_controls, 0, sizeof(struct v4l2_ext_controls)); - memset(&control, 0, sizeof(struct v4l2_ext_control)); - - if (ctrl == NULL) + if (cmng == NULL) { return -EINVAL; } - /* Replace to VIDIOC_G_EXT_CTRLS format */ - - control.id = ctrl->id; - - ext_controls.ctrl_class = V4L2_CTRL_CLASS_USER; - ext_controls.count = 1; - ext_controls.controls = &control; - - /* Execute VIDIOC_G_EXT_CTRLS */ + type_inf = get_capture_type_inf(cmng, type); + if (type_inf == NULL) + { + return -EINVAL; + } - ret = video_g_ext_ctrls(priv, &ext_controls); - if (ret == OK) + if (!is_sem_waited(&type_inf->wait_capture.dqbuf_wait_flg)) { - /* Replace gotten value to VIDIOC_G_CTRL parameter */ + /* In not waiting DQBUF case, return OK */ - ctrl->value = control.value; + return OK; } - return ret; + type_inf->wait_capture.waitend_cause = WAITEND_CAUSE_DQCANCEL; + + /* If capture is done before nxsem_post, cause is overwritten */ + + return nxsem_post(&type_inf->wait_capture.dqbuf_wait_flg); } -static int video_s_ctrl(FAR struct video_mng_s *priv, - FAR struct v4l2_control *ctrl) +static int capture_g_fmt(FAR struct v4l2_s *v4l2, + FAR struct v4l2_format *fmt) { - struct v4l2_ext_controls ext_controls; - struct v4l2_ext_control control; + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; - if (ctrl == NULL) + if (cmng == NULL) { return -EINVAL; } - /* Replace to VIDIOC_S_EXT_CTRLS format */ - - control.id = ctrl->id; - control.value = ctrl->value; - - ext_controls.ctrl_class = V4L2_CTRL_CLASS_USER; - ext_controls.count = 1; - ext_controls.controls = &control; + type_inf = get_capture_type_inf(cmng, fmt->type); + if (type_inf == NULL) + { + return -EINVAL; + } - /* Execute VIDIOC_S_EXT_CTRLS */ + memset(&fmt->fmt, 0, sizeof(fmt->fmt)); + fmt->fmt.pix.width = type_inf->fmt[CAPTURE_FMT_MAIN].width; + fmt->fmt.pix.height = type_inf->fmt[CAPTURE_FMT_MAIN].height; + fmt->fmt.pix.pixelformat = type_inf->fmt[CAPTURE_FMT_MAIN].pixelformat; - return video_s_ext_ctrls(priv, &ext_controls); + return OK; } -static int video_g_ext_ctrls(FAR struct video_mng_s *priv, - FAR struct v4l2_ext_controls *ctrls) +static int capture_s_fmt(FAR struct v4l2_s *v4l2, + FAR struct v4l2_format *fmt) { - FAR struct v4l2_ext_control *control; - int ret = OK; - int cnt; - - ASSERT(priv->imgsensor); + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; + int ret; - if (priv == NULL || ctrls == NULL) + if (cmng == NULL) { return -EINVAL; } - for (cnt = 0, control = ctrls->controls; - cnt < ctrls->count; - cnt++, control++) + ret = capture_try_fmt(v4l2, fmt); + if (ret != 0) { - ret = IMGSENSOR_GET_VALUE(priv->imgsensor, - VIDEO_ID(ctrls->ctrl_class, control->id), - control->size, - (imgsensor_value_t *)&control->value64); - if (ret < 0) - { - /* Set cnt in that error occurred */ - - ctrls->error_idx = cnt; - return ret; - } + return ret; } - return ret; -} - -static int set_intvalue(FAR video_mng_t *vmng, - uint32_t id, int32_t value32) -{ - imgsensor_value_t value; + type_inf = get_capture_type_inf(cmng, fmt->type); + if (type_inf == NULL) + { + return -EINVAL; + } - ASSERT(vmng->imgsensor); + if (type_inf->state != CAPTURE_STATE_STREAMOFF) + { + return -EBUSY; + } - value.value32 = value32; - return IMGSENSOR_SET_VALUE(vmng->imgsensor, id, sizeof(int32_t), value); -} + switch (fmt->fmt.pix.pixelformat) + { + case V4L2_PIX_FMT_SUBIMG_UYVY: + case V4L2_PIX_FMT_SUBIMG_RGB565: + if (type_inf->fmt[CAPTURE_FMT_MAIN].pixelformat != + V4L2_PIX_FMT_JPEG_WITH_SUBIMG) + { + return -EPERM; + } -static int set_pvalue(FAR video_mng_t *vmng, - uint32_t id, int size, void *pval) -{ - imgsensor_value_t value; + type_inf->fmt[CAPTURE_FMT_SUB].width = fmt->fmt.pix.width; + type_inf->fmt[CAPTURE_FMT_SUB].height = fmt->fmt.pix.height; + type_inf->fmt[CAPTURE_FMT_SUB].pixelformat = + fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_SUBIMG_UYVY ? + V4L2_PIX_FMT_UYVY : V4L2_PIX_FMT_RGB565; + type_inf->nr_fmt = 2; + break; - ASSERT(vmng->imgsensor); + default: + type_inf->fmt[CAPTURE_FMT_MAIN].width = fmt->fmt.pix.width; + type_inf->fmt[CAPTURE_FMT_MAIN].height = fmt->fmt.pix.height; + type_inf->fmt[CAPTURE_FMT_MAIN].pixelformat = + fmt->fmt.pix.pixelformat; + type_inf->nr_fmt = 1; + break; + } - value.p_u8 = (FAR uint8_t *)pval; - return IMGSENSOR_SET_VALUE(vmng->imgsensor, id, size, value); + return OK; } -static video_scene_params_t *search_scene_param(FAR video_mng_t *vmng, - enum v4l2_scene_mode mode) +static int capture_try_fmt(FAR struct v4l2_s *v4l2, + FAR struct v4l2_format *fmt) { - int i; + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; + video_format_t vf[MAX_CAPTURE_FMT]; + uint8_t nr_fmt; - for (i = 0; i < vmng->video_scence_num; i++) + if (cmng == NULL || fmt == NULL) { - if (vmng->video_scene_param[i]->mode == mode) - { - return vmng->video_scene_param[i]; - } + return -EINVAL; } - return NULL; -} - -static int reflect_scene_parameter(FAR video_mng_t *vmng, - enum v4l2_scene_mode mode) -{ - video_scene_params_t *sp; + ASSERT(cmng->imgsensor && cmng->imgdata); - sp = search_scene_param(vmng, mode); - if (sp == NULL) + type_inf = get_capture_type_inf(cmng, fmt->type); + if (type_inf == NULL) { - /* Unsupported scene mode */ - return -EINVAL; } - set_intvalue(vmng, IMGSENSOR_ID_BRIGHTNESS, sp->brightness); - set_intvalue(vmng, IMGSENSOR_ID_CONTRAST, sp->contrast); - set_intvalue(vmng, IMGSENSOR_ID_SATURATION, sp->saturation); - set_intvalue(vmng, IMGSENSOR_ID_HUE , sp->hue); - set_intvalue(vmng, IMGSENSOR_ID_AUTO_WHITE_BALANCE, sp->awb); - set_intvalue(vmng, IMGSENSOR_ID_RED_BALANCE , sp->red); - set_intvalue(vmng, IMGSENSOR_ID_BLUE_BALANCE, sp->blue); - set_intvalue(vmng, IMGSENSOR_ID_GAMMA, sp->gamma); - set_pvalue(vmng, IMGSENSOR_ID_GAMMA_CURVE, - sp->gamma_curve_sz, sp->gamma_curve); - set_intvalue(vmng, IMGSENSOR_ID_EXPOSURE, sp->ev); - set_intvalue(vmng, IMGSENSOR_ID_HFLIP_VIDEO, sp->hflip_video); - set_intvalue(vmng, IMGSENSOR_ID_VFLIP_VIDEO, sp->vflip_video); - set_intvalue(vmng, IMGSENSOR_ID_HFLIP_STILL, sp->hflip_still); - set_intvalue(vmng, IMGSENSOR_ID_VFLIP_STILL, sp->vflip_still); - set_intvalue(vmng, IMGSENSOR_ID_SHARPNESS, sp->sharpness); - set_intvalue(vmng, IMGSENSOR_ID_COLORFX, sp->colorfx); - set_intvalue(vmng, IMGSENSOR_ID_AUTOBRIGHTNESS, sp->auto_brightness); - set_intvalue(vmng, IMGSENSOR_ID_ROTATE, sp->rotate); - set_intvalue(vmng, IMGSENSOR_ID_EXPOSURE_AUTO, sp->ae); - if (sp->ae == V4L2_EXPOSURE_MANUAL || - sp->ae == V4L2_EXPOSURE_SHUTTER_PRIORITY) + switch (fmt->fmt.pix.pixelformat) { - set_intvalue(vmng, IMGSENSOR_ID_EXPOSURE_ABSOLUTE, sp->exposure_time); - } + case V4L2_PIX_FMT_SUBIMG_UYVY: + case V4L2_PIX_FMT_SUBIMG_RGB565: + if (type_inf->fmt[CAPTURE_FMT_MAIN].pixelformat != + V4L2_PIX_FMT_JPEG_WITH_SUBIMG) + { + return -EPERM; + } - set_intvalue(vmng, IMGSENSOR_ID_FOCUS_ABSOLUTE, sp->focus); - set_intvalue(vmng, IMGSENSOR_ID_FOCUS_AUTO, sp->af); - set_intvalue(vmng, IMGSENSOR_ID_ZOOM_ABSOLUTE, sp->zoom); - if (sp->ae == V4L2_EXPOSURE_MANUAL || - sp->ae == V4L2_EXPOSURE_APERTURE_PRIORITY) - { - set_intvalue(vmng, IMGSENSOR_ID_IRIS_ABSOLUTE, sp->iris); - } + /* Validate both main image and subimage. */ - set_intvalue(vmng, IMGSENSOR_ID_AUTO_N_PRESET_WB, sp->wb); - set_intvalue(vmng, IMGSENSOR_ID_WIDE_DYNAMIC_RANGE, sp->wdr); - set_intvalue(vmng, IMGSENSOR_ID_IMG_STABILIZATION, sp->stabilization); - set_intvalue(vmng, IMGSENSOR_ID_ISO_SENSITIVITY_AUTO, sp->iso_auto); - if (sp->iso_auto == V4L2_ISO_SENSITIVITY_MANUAL) - { - set_intvalue(vmng, IMGSENSOR_ID_ISO_SENSITIVITY, sp->iso); - } + nr_fmt = 2; + memcpy(&vf[CAPTURE_FMT_MAIN], + &type_inf->fmt[CAPTURE_FMT_MAIN], + sizeof(video_format_t)); + vf[CAPTURE_FMT_SUB].width = fmt->fmt.pix.width; + vf[CAPTURE_FMT_SUB].height = fmt->fmt.pix.height; + vf[CAPTURE_FMT_SUB].pixelformat = + fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_SUBIMG_UYVY ? + V4L2_PIX_FMT_UYVY : V4L2_PIX_FMT_RGB565; + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_JPEG: + case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: + nr_fmt = 1; + vf[CAPTURE_FMT_MAIN].width = fmt->fmt.pix.width; + vf[CAPTURE_FMT_MAIN].height = fmt->fmt.pix.height; + vf[CAPTURE_FMT_MAIN].pixelformat = fmt->fmt.pix.pixelformat; + break; - set_intvalue(vmng, IMGSENSOR_ID_EXPOSURE_METERING, sp->meter); - set_intvalue(vmng, IMGSENSOR_ID_3A_LOCK, sp->threea_lock); - set_intvalue(vmng, IMGSENSOR_ID_FLASH_LED_MODE, sp->led); - set_intvalue(vmng, IMGSENSOR_ID_JPEG_QUALITY, sp->jpeg_quality); + default: + return -EINVAL; + } - vmng->video_scene_mode = mode; - return OK; + return validate_frame_setting(cmng, + fmt->type, + nr_fmt, + vf, + &type_inf->clip, + &type_inf->frame_interval); } -static int video_s_ext_ctrls(FAR struct video_mng_s *priv, - FAR struct v4l2_ext_controls *ctrls) +static int capture_g_parm(FAR struct v4l2_s *v4l2, + FAR struct v4l2_streamparm *parm) { - FAR struct v4l2_ext_control *control; - int ret = OK; - int cnt; + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; + int ret = -EINVAL; + + if (cmng == NULL || parm == NULL) + { + return -EINVAL; + } - ASSERT(priv->imgsensor); + DEBUGASSERT(cmng->imgsensor); - if (priv == NULL || ctrls == NULL) + type_inf = get_capture_type_inf(cmng, parm->type); + if (type_inf == NULL) { return -EINVAL; } - for (cnt = 0, control = ctrls->controls; - cnt < ctrls->count; - cnt++, control++) + memset(&parm->parm, 0, sizeof(parm->parm)); + + if (type_inf->state == CAPTURE_STATE_CAPTURE) { - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_CAMERA && - control->id == V4L2_CID_SCENE_MODE) - { - ret = reflect_scene_parameter(priv, control->value); - } - else - { - ret = IMGSENSOR_SET_VALUE(priv->imgsensor, - VIDEO_ID(ctrls->ctrl_class, control->id), - control->size, - (imgsensor_value_t)control->value64); - if (ret == 0) - { - if (priv->video_scene_mode == V4L2_SCENE_MODE_NONE) - { - save_scene_param(priv, V4L2_SCENE_MODE_NONE, - VIDEO_ID(ctrls->ctrl_class, control->id), - control); - } - } - } + /* If capture is started and lower driver has the get_frame_interval(), + * query lower driver. + */ - if (ret < 0) - { - /* Set cnt in that error occurred */ + ret = IMGSENSOR_GET_FRAME_INTERVAL(cmng->imgsensor, parm->type, + (imgsensor_interval_t *)&parm->parm.capture.timeperframe); + } - ctrls->error_idx = cnt; - return ret; - } + if (ret != OK) + { + /* In no capture state or error case, return stored value. */ + + memcpy(&parm->parm.capture.timeperframe, + &type_inf->frame_interval, + sizeof(struct v4l2_fract)); } - return ret; + parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + return OK; } -static int video_query_ext_ctrl_scene(FAR video_mng_t *vmng, - FAR struct v4s_query_ext_ctrl_scene *attr) +static int capture_s_parm(FAR struct v4l2_s *v4l2, + FAR struct v4l2_streamparm *parm) { - if (attr == NULL) + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; + int ret; + + if (cmng == NULL || parm == NULL) { return -EINVAL; } - return video_query_ext_ctrl(vmng, &attr->control); -} + ASSERT(cmng->imgsensor && cmng->imgdata); -static int video_querymenu_scene(FAR video_mng_t *vmng, - FAR struct v4s_querymenu_scene *menu) -{ - if (menu == NULL) + type_inf = get_capture_type_inf(cmng, parm->type); + if (type_inf == NULL) { return -EINVAL; } - return video_querymenu(vmng, &menu->menu); + if (type_inf->state != CAPTURE_STATE_STREAMOFF) + { + return -EBUSY; + } + + ret = validate_frame_setting(cmng, + parm->type, + type_inf->nr_fmt, + type_inf->fmt, + &type_inf->clip, + &parm->parm.capture.timeperframe); + if (ret != OK) + { + return ret; + } + + memcpy(&type_inf->frame_interval, + &parm->parm.capture.timeperframe, + sizeof(struct v4l2_fract)); + + return ret; } -static int read_scene_param(FAR struct video_mng_s *vmng, - enum v4l2_scene_mode mode, - uint32_t id, - struct v4l2_ext_control *control) +static int capture_streamon(FAR struct v4l2_s *v4l2, + FAR enum v4l2_buf_type *type) { - imgsensor_supported_value_t value; - video_scene_params_t *sp; + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; + enum capture_state_e next_capture_state; int ret = OK; - ASSERT(vmng->imgsensor); - - if (control == NULL) + if (cmng == NULL || type == NULL) { return -EINVAL; } - sp = search_scene_param(vmng, mode); - if (sp == NULL) + type_inf = get_capture_type_inf(cmng, *type); + if (type_inf == NULL) { - /* Unsupported scene mode */ - return -EINVAL; } - ret = IMGSENSOR_GET_SUPPORTED_VALUE(vmng->imgsensor, id, &value); - if (ret < 0) + if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - /* Unsupported camera parameter */ + /* No procedure for VIDIOC_STREAMON(STILL_CAPTURE) */ - return ret; + return OK; } - switch (id) + nxmutex_lock(&type_inf->lock_state); + + if (type_inf->state != CAPTURE_STATE_STREAMOFF) { - case IMGSENSOR_ID_BRIGHTNESS: - control->value = sp->brightness; - break; + ret = -EPERM; + } + else + { + next_capture_state = + estimate_next_capture_state(cmng, CAUSE_CAPTURE_START); + change_capture_state(cmng, next_capture_state); + } - case IMGSENSOR_ID_CONTRAST: - control->value = sp->contrast; - break; + nxmutex_unlock(&type_inf->lock_state); + return ret; +} - case IMGSENSOR_ID_SATURATION: - control->value = sp->saturation; - break; +static int capture_streamoff(FAR struct v4l2_s *v4l2, + FAR enum v4l2_buf_type *type) +{ + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; + enum capture_state_e next_capture_state; + irqstate_t flags; + int ret = OK; - case IMGSENSOR_ID_HUE: - control->value = sp->hue; - break; + if (cmng == NULL || type == NULL) + { + return -EINVAL; + } - case IMGSENSOR_ID_AUTO_WHITE_BALANCE: - control->value = sp->awb; - break; + type_inf = get_capture_type_inf(cmng, *type); + if (type_inf == NULL) + { + return -EINVAL; + } - case IMGSENSOR_ID_RED_BALANCE: - control->value = sp->red; - break; + if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + { + /* No procedure for VIDIOC_STREAMOFF(STILL_CAPTURE) */ - case IMGSENSOR_ID_BLUE_BALANCE: - control->value = sp->blue; - break; + return OK; + } - case IMGSENSOR_ID_GAMMA: - control->value = sp->gamma; - break; + flags = enter_critical_section(); - case IMGSENSOR_ID_GAMMA_CURVE: - memcpy(control->p_u8, - sp->gamma_curve, - sp->gamma_curve_sz); - break; + if (type_inf->state == CAPTURE_STATE_STREAMOFF) + { + ret = -EPERM; + } + else + { + next_capture_state = + estimate_next_capture_state(cmng, CAUSE_CAPTURE_STOP); + change_capture_state(cmng, next_capture_state); + } - case IMGSENSOR_ID_EXPOSURE: - control->value = sp->ev; - break; + leave_critical_section(flags); - case IMGSENSOR_ID_HFLIP_VIDEO: - control->value = sp->hflip_video; - break; + return ret; +} - case IMGSENSOR_ID_VFLIP_VIDEO: - control->value = sp->vflip_video; - break; +static int capture_do_halfpush(FAR struct v4l2_s *v4l2, bool enable) +{ + struct v4l2_ext_controls ext_controls; + struct v4l2_ext_control control[2]; - case IMGSENSOR_ID_HFLIP_STILL: - control->value = sp->hflip_still; - break; + if (v4l2 == NULL) + { + return -EINVAL; + } - case IMGSENSOR_ID_VFLIP_STILL: - control->value = sp->vflip_still; - break; + /* Replace to VIDIOC_S_EXT_CTRLS format */ - case IMGSENSOR_ID_SHARPNESS: - control->value = sp->sharpness; - break; + control[0].id = V4L2_CID_3A_LOCK; + control[0].value = enable ? + V4L2_LOCK_EXPOSURE | V4L2_LOCK_WHITE_BALANCE : 0; + control[1].id = V4L2_CID_AUTO_FOCUS_START; + control[1].value = enable ? true : false; - case IMGSENSOR_ID_COLOR_KILLER: - control->value = sp->colorfx == V4L2_COLORFX_BW; - break; + ext_controls.ctrl_class = V4L2_CTRL_CLASS_CAMERA; + ext_controls.count = 2; + ext_controls.controls = control; - case IMGSENSOR_ID_COLORFX: - control->value = sp->colorfx; - break; + /* Execute VIDIOC_S_EXT_CTRLS */ - case IMGSENSOR_ID_AUTOBRIGHTNESS: - control->value = sp->auto_brightness; - break; + return capture_s_ext_ctrls(v4l2, &ext_controls); +} - case IMGSENSOR_ID_ROTATE: - control->value = sp->rotate; - break; +static int capture_takepict_start(FAR struct v4l2_s *v4l2, + int32_t capture_num) +{ + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + enum capture_state_e next_capture_state; + FAR vbuf_container_t *container; + irqstate_t flags; + int ret = OK; - case IMGSENSOR_ID_EXPOSURE_AUTO: - control->value = sp->ae; - break; + if (cmng == NULL) + { + return -EINVAL; + } - case IMGSENSOR_ID_EXPOSURE_ABSOLUTE: - control->value = sp->exposure_time; - break; + nxmutex_lock(&cmng->still_inf.lock_state); - case IMGSENSOR_ID_FOCUS_ABSOLUTE: - control->value = sp->focus; - break; + if (cmng->still_inf.state != CAPTURE_STATE_STREAMOFF) + { + ret = -EPERM; + } + else + { + if (capture_num > 0) + { + cmng->still_inf.remaining_capnum = capture_num; + } + else + { + cmng->still_inf.remaining_capnum = REMAINING_CAPNUM_INFINITY; + } - case IMGSENSOR_ID_FOCUS_AUTO: - control->value = sp->af; - break; + /* Control video stream prior to still stream */ - case IMGSENSOR_ID_ZOOM_ABSOLUTE: - control->value = sp->zoom; - break; + flags = enter_critical_section(); - case IMGSENSOR_ID_IRIS_ABSOLUTE: - control->value = sp->iris; - break; + next_capture_state = estimate_next_capture_state(cmng, + CAUSE_STILL_START); + change_capture_state(cmng, next_capture_state); - case IMGSENSOR_ID_AUTO_N_PRESET_WB: - control->value = sp->wb; - break; + leave_critical_section(flags); - case IMGSENSOR_ID_WIDE_DYNAMIC_RANGE: - control->value = sp->wdr; - break; + container = + video_framebuff_get_vacant_container(&cmng->still_inf.bufinf); + if (container != NULL) + { + /* Start still stream capture */ - case IMGSENSOR_ID_IMG_STABILIZATION: - control->value = sp->stabilization; - break; + start_capture(cmng, + V4L2_BUF_TYPE_STILL_CAPTURE, + cmng->still_inf.nr_fmt, + cmng->still_inf.fmt, + &cmng->still_inf.clip, + &cmng->still_inf.frame_interval, + container->buf.m.userptr, + container->buf.length); - case IMGSENSOR_ID_ISO_SENSITIVITY: - control->value = sp->iso; - break; + cmng->still_inf.state = CAPTURE_STATE_CAPTURE; + } + else + { + cmng->still_inf.state = CAPTURE_STATE_STREAMON; + } + } - case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO: - control->value = sp->iso_auto; - break; + nxmutex_unlock(&cmng->still_inf.lock_state); + return ret; +} - case IMGSENSOR_ID_EXPOSURE_METERING: - control->value = sp->meter; - break; +static int capture_takepict_stop(FAR struct v4l2_s *v4l2, + bool halfpush) +{ + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + enum capture_state_e next_capture_state; + irqstate_t flags; + int ret = OK; - case IMGSENSOR_ID_SPOT_POSITION: - control->value = sp->spot_pos; - break; + if (cmng == NULL) + { + return -EINVAL; + } - case IMGSENSOR_ID_3A_LOCK: - control->value = sp->threea_lock; - break; + nxmutex_lock(&cmng->still_inf.lock_state); - case IMGSENSOR_ID_FLASH_LED_MODE: - control->value = sp->led; - break; + if (cmng->still_inf.state == CAPTURE_STATE_STREAMOFF && + cmng->still_inf.remaining_capnum == REMAINING_CAPNUM_INFINITY) + { + ret = -EPERM; + } + else + { + flags = enter_critical_section(); + if (cmng->still_inf.state == CAPTURE_STATE_CAPTURE) + { + stop_capture(cmng, V4L2_BUF_TYPE_STILL_CAPTURE); + } - case IMGSENSOR_ID_JPEG_QUALITY: - control->value = sp->jpeg_quality; - break; + leave_critical_section(flags); - default: - ret = -EINVAL; - break; + cmng->still_inf.state = CAPTURE_STATE_STREAMOFF; + cmng->still_inf.remaining_capnum = REMAINING_CAPNUM_INFINITY; + + /* Control video stream */ + + nxmutex_lock(&cmng->capture_inf.lock_state); + next_capture_state = estimate_next_capture_state(cmng, + CAUSE_STILL_STOP); + change_capture_state(cmng, next_capture_state); + nxmutex_unlock(&cmng->capture_inf.lock_state); } + nxmutex_unlock(&cmng->still_inf.lock_state); return ret; } -static int video_g_ext_ctrls_scene(FAR video_mng_t *vmng, - FAR struct v4s_ext_controls_scene *ctrls) +static int capture_s_selection(FAR struct v4l2_s *v4l2, + FAR struct v4l2_selection *clip) { - FAR struct v4l2_ext_control *control; - int ret = OK; - int cnt; + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; + uint32_t p_u32[IMGSENSOR_CLIP_NELEM]; + imgsensor_value_t val; + int32_t id; + int ret; - if (ctrls == NULL) + if (cmng == NULL || clip == NULL) { return -EINVAL; } - for (cnt = 0, control = ctrls->control.controls; - cnt < ctrls->control.count; - cnt++, control++) + ASSERT(cmng->imgsensor); + + type_inf = get_capture_type_inf(cmng, clip->type); + if (type_inf == NULL) { - ret = read_scene_param(vmng, ctrls->mode, - VIDEO_ID(ctrls->control.ctrl_class, control->id), - control); - if (ret != OK) - { - ctrls->control.error_idx = cnt; - return ret; - } + return -EINVAL; + } + + if (type_inf->state != CAPTURE_STATE_STREAMOFF) + { + return -EBUSY; + } + + if (!validate_clip_setting(&clip->r, type_inf->fmt)) + { + return -EINVAL; + } + + ret = validate_frame_setting(cmng, + clip->type, + type_inf->nr_fmt, + type_inf->fmt, + &clip->r, + &type_inf->frame_interval); + if (ret != OK) + { + return ret; + } + + id = clip->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? + IMGSENSOR_ID_CLIP_VIDEO : IMGSENSOR_ID_CLIP_STILL; + + p_u32[IMGSENSOR_CLIP_INDEX_LEFT] = clip->r.left; + p_u32[IMGSENSOR_CLIP_INDEX_TOP] = clip->r.top; + p_u32[IMGSENSOR_CLIP_INDEX_WIDTH] = clip->r.width; + p_u32[IMGSENSOR_CLIP_INDEX_HEIGHT] = clip->r.height; + + val.p_u32 = p_u32; + ret = IMGSENSOR_SET_VALUE(cmng->imgsensor, id, sizeof(p_u32), val); + if (ret != OK) + { + return ret; } + memcpy(&type_inf->clip, &clip->r, sizeof(struct v4l2_rect)); return ret; } -static int check_range(int64_t value, - int64_t min, - int64_t max, - uint64_t step) +static int capture_g_selection(FAR struct v4l2_s *v4l2, + FAR struct v4l2_selection *clip) { - if (value < min || value > max || - (value - min) % step != 0) + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR capture_type_inf_t *type_inf; + + if (cmng == NULL || clip == NULL) + { + return -EINVAL; + } + + type_inf = get_capture_type_inf(cmng, clip->type); + if (type_inf == NULL) { return -EINVAL; } + memcpy(&clip->r, &type_inf->clip, sizeof(struct v4l2_rect)); return OK; } -static int save_scene_param(FAR video_mng_t *vmng, - enum v4l2_scene_mode mode, - uint32_t id, - struct v4l2_ext_control *control) +static int capture_queryctrl(FAR struct v4l2_s *v4l2, + FAR struct v4l2_queryctrl *ctrl) { + struct v4l2_query_ext_ctrl ext_ctrl; + int ret; + + if (v4l2 == NULL || ctrl == NULL) + { + return -EINVAL; + } + + /* Replace to VIDIOC_QUERY_EXT_CTRL format */ + + ext_ctrl.ctrl_class = ctrl->ctrl_class; + ext_ctrl.id = ctrl->id; + + ret = capture_query_ext_ctrl(v4l2, &ext_ctrl); + if (ret != OK) + { + return ret; + } + + if (ext_ctrl.type == V4L2_CTRL_TYPE_INTEGER64 || + ext_ctrl.type == V4L2_CTRL_TYPE_U8 || + ext_ctrl.type == V4L2_CTRL_TYPE_U16 || + ext_ctrl.type == V4L2_CTRL_TYPE_U32) + { + /* Unsupported type in VIDIOC_QUERYCTRL */ + + return -EINVAL; + } + + /* Replace gotten value to VIDIOC_QUERYCTRL */ + + ctrl->type = ext_ctrl.type; + ctrl->minimum = ext_ctrl.minimum; + ctrl->maximum = ext_ctrl.maximum; + ctrl->step = ext_ctrl.step; + ctrl->default_value = ext_ctrl.default_value; + ctrl->flags = ext_ctrl.flags; + strlcpy(ctrl->name, ext_ctrl.name, sizeof(ctrl->name)); + + return OK; +} + +static int capture_query_ext_ctrl(FAR struct v4l2_s *v4l2, + FAR struct v4l2_query_ext_ctrl *attr) +{ + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; imgsensor_supported_value_t value; imgsensor_capability_range_t *range = &value.u.range; imgsensor_capability_discrete_t *disc = &value.u.discrete; imgsensor_capability_elems_t *elem = &value.u.elems; - video_scene_params_t *sp; int ret; - int i; - ASSERT(vmng->imgsensor); - - sp = search_scene_param(vmng, mode); - if (sp == NULL) + if (cmng == NULL || attr == NULL) { - /* Unsupported scene mode */ - return -EINVAL; } - ret = IMGSENSOR_GET_SUPPORTED_VALUE(vmng->imgsensor, id, &value); - if (ret < 0) + ASSERT(cmng->imgsensor); + + attr->flags = 0; + attr->elem_size = 0; + attr->nr_of_dims = 0; + memset(attr->dims, 0, sizeof(attr->dims)); + + if (attr->ctrl_class == V4L2_CTRL_CLASS_CAMERA && + attr->id == V4L2_CID_SCENE_MODE) { - /* Unsupported camera parameter */ + /* Scene mode is processed in only video driver. */ - return ret; + attr->type = V4L2_CTRL_TYPE_INTEGER_MENU; + attr->minimum = 0; + attr->maximum = cmng->capture_scence_num - 1; + attr->step = 1; + attr->default_value = 0; + attr->flags = 0; + strlcpy(attr->name, "Scene Mode", 32); } - - switch (value.type) + else { - case IMGSENSOR_CTRL_TYPE_INTEGER_MENU: - for (i = 0; i < disc->nr_values; i++) - { - if (control->value == disc->values[i]) - { - break; - } - } + ret = IMGSENSOR_GET_SUPPORTED_VALUE(cmng->imgsensor, + CAPTURE_ID(attr->ctrl_class, attr->id), + &value); + if (ret < 0) + { + return ret; + } - if (i >= disc->nr_values) - { - return -EINVAL; - } + attr->type = value.type; + attr->flags = 0; - break; + switch (value.type) + { + case IMGSENSOR_CTRL_TYPE_INTEGER_MENU: + attr->minimum = 0; + attr->maximum = disc->nr_values - 1; + attr->step = 1; + attr->default_value = disc->default_value; + break; - case IMGSENSOR_CTRL_TYPE_U8: - if (control->size < elem->nr_elems * sizeof(uint8_t)) - { - return -EINVAL; - } + case IMGSENSOR_CTRL_TYPE_U8: + case IMGSENSOR_CTRL_TYPE_U16: + case IMGSENSOR_CTRL_TYPE_U32: + attr->minimum = elem->minimum; + attr->maximum = elem->maximum; + attr->step = elem->step; + attr->elems = elem->nr_elems; + break; - for (i = 0; i < elem->nr_elems; i++) - { - ret = check_range(control->p_u8[i], - elem->minimum, - elem->maximum, - elem->step); - if (ret != OK) - { - return ret; - } - } + default: + attr->minimum = range->minimum; + attr->maximum = range->maximum; + attr->step = range->step; + attr->default_value = range->default_value; + break; + } - break; + set_parameter_name(CAPTURE_ID(attr->ctrl_class, attr->id), + attr->name); + } - case IMGSENSOR_CTRL_TYPE_U16: - if (control->size < elem->nr_elems * sizeof(uint16_t)) - { - return -EINVAL; - } + return OK; +} - for (i = 0; i < elem->nr_elems; i++) - { - ret = check_range(control->p_u16[i], - elem->minimum, - elem->maximum, - elem->step); - if (ret != OK) - { - return ret; - } - } +static int capture_querymenu(FAR struct v4l2_s *v4l2, + FAR struct v4l2_querymenu *menu) +{ + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + imgsensor_supported_value_t value; + int ret; - break; + if (cmng == NULL || menu == NULL) + { + return -EINVAL; + } - case IMGSENSOR_CTRL_TYPE_U32: - if (control->size < elem->nr_elems * sizeof(uint32_t)) - { - return -EINVAL; - } + ASSERT(cmng->imgsensor); - for (i = 0; i < elem->nr_elems; i++) - { - ret = check_range(control->p_u32[i], - elem->minimum, - elem->maximum, - elem->step); - if (ret != OK) - { - return ret; - } - } + if (menu->ctrl_class == V4L2_CTRL_CLASS_CAMERA && + menu->id == V4L2_CID_SCENE_MODE) + { + /* Scene mode is processed in only video driver. */ - break; + if (menu->index > cmng->capture_scence_num - 1) + { + return -EINVAL; + } - default: - ret = check_range(control->value, - range->minimum, - range->maximum, - range->step); - if (ret != OK) - { - return ret; - } + menu->value = cmng->capture_scene_param[menu->index]->mode; + } + else + { + ret = IMGSENSOR_GET_SUPPORTED_VALUE(cmng->imgsensor, + CAPTURE_ID(menu->ctrl_class, menu->id), + &value); + if (ret < 0) + { + return ret; + } - break; + if (value.type != IMGSENSOR_CTRL_TYPE_INTEGER_MENU) + { + /* VIDIOC_QUERYMENU is used only for + * IMGSENSOR_CTRL_TYPE_INTEGER_MENU. + */ + + return -EINVAL; + } + + if (menu->index >= value.u.discrete.nr_values) + { + return -EINVAL; + } + + menu->value = value.u.discrete.values[menu->index]; } - switch (id) + return OK; +} + +static int capture_g_ctrl(FAR struct v4l2_s *v4l2, + FAR struct v4l2_control *ctrl) +{ + struct v4l2_ext_controls ext_controls; + struct v4l2_ext_control control; + int ret; + + if (v4l2 == NULL || ctrl == NULL) { - case IMGSENSOR_ID_BRIGHTNESS: - sp->brightness = control->value; - break; + return -EINVAL; + } - case IMGSENSOR_ID_CONTRAST: - sp->contrast = control->value; - break; + memset(&ext_controls, 0, sizeof(struct v4l2_ext_controls)); + memset(&control, 0, sizeof(struct v4l2_ext_control)); - case IMGSENSOR_ID_SATURATION: - sp->saturation = control->value; - break; + /* Replace to VIDIOC_G_EXT_CTRLS format */ - case IMGSENSOR_ID_HUE: - sp->hue = control->value; - break; + control.id = ctrl->id; - case IMGSENSOR_ID_AUTO_WHITE_BALANCE: - sp->awb = control->value; - break; + ext_controls.ctrl_class = V4L2_CTRL_CLASS_USER; + ext_controls.count = 1; + ext_controls.controls = &control; - case IMGSENSOR_ID_RED_BALANCE: - sp->red = control->value; - break; + /* Execute VIDIOC_G_EXT_CTRLS */ - case IMGSENSOR_ID_BLUE_BALANCE: - sp->blue = control->value; - break; + ret = capture_g_ext_ctrls(v4l2, &ext_controls); + if (ret == OK) + { + /* Replace gotten value to VIDIOC_G_CTRL parameter */ - case IMGSENSOR_ID_GAMMA: - sp->gamma = control->value; - break; + ctrl->value = control.value; + } - case IMGSENSOR_ID_GAMMA_CURVE: - memcpy(sp->gamma_curve, - control->p_u8, - sp->gamma_curve_sz); - break; + return ret; +} - case IMGSENSOR_ID_EXPOSURE: - sp->ev = control->value; - break; +static int capture_s_ctrl(FAR struct v4l2_s *v4l2, + FAR struct v4l2_control *ctrl) +{ + struct v4l2_ext_controls ext_controls; + struct v4l2_ext_control control; - case IMGSENSOR_ID_HFLIP_VIDEO: - sp->hflip_video = control->value; - break; + if (v4l2 == NULL || ctrl == NULL) + { + return -EINVAL; + } - case IMGSENSOR_ID_VFLIP_VIDEO: - sp->vflip_video = control->value; - break; + /* Replace to VIDIOC_S_EXT_CTRLS format */ - case IMGSENSOR_ID_HFLIP_STILL: - sp->hflip_still = control->value; - break; + control.id = ctrl->id; + control.value = ctrl->value; - case IMGSENSOR_ID_VFLIP_STILL: - sp->vflip_still = control->value; - break; + ext_controls.ctrl_class = V4L2_CTRL_CLASS_USER; + ext_controls.count = 1; + ext_controls.controls = &control; - case IMGSENSOR_ID_SHARPNESS: - sp->sharpness = control->value; - break; + /* Execute VIDIOC_S_EXT_CTRLS */ - case IMGSENSOR_ID_COLOR_KILLER: - sp->colorfx = control->value ? V4L2_COLORFX_BW : V4L2_COLORFX_NONE; - break; + return capture_s_ext_ctrls(v4l2, &ext_controls); +} - case IMGSENSOR_ID_COLORFX: - sp->colorfx = control->value; - break; +static int capture_g_ext_ctrls(FAR struct v4l2_s *v4l2, + FAR struct v4l2_ext_controls *ctrls) +{ + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR struct v4l2_ext_control *control; + int ret = OK; + int cnt; - case IMGSENSOR_ID_AUTOBRIGHTNESS: - sp->auto_brightness = control->value; - break; + if (cmng == NULL || ctrls == NULL) + { + return -EINVAL; + } - case IMGSENSOR_ID_ROTATE: - sp->rotate = control->value; - break; + ASSERT(cmng->imgsensor); - case IMGSENSOR_ID_EXPOSURE_AUTO: - sp->ae = control->value; - break; + for (cnt = 0, control = ctrls->controls; + cnt < ctrls->count; + cnt++, control++) + { + ret = IMGSENSOR_GET_VALUE(cmng->imgsensor, + CAPTURE_ID(ctrls->ctrl_class, control->id), + control->size, + (imgsensor_value_t *)&control->value64); + if (ret < 0) + { + /* Set cnt in that error occurred */ - case IMGSENSOR_ID_EXPOSURE_ABSOLUTE: - sp->exposure_time = control->value; - break; + ctrls->error_idx = cnt; + return ret; + } + } - case IMGSENSOR_ID_FOCUS_ABSOLUTE: - sp->focus = control->value; - break; + return ret; +} - case IMGSENSOR_ID_FOCUS_AUTO: - sp->af = control->value; - break; +static int capture_s_ext_ctrls(FAR struct v4l2_s *v4l2, + FAR struct v4l2_ext_controls *ctrls) +{ + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR struct v4l2_ext_control *control; + int ret = OK; + int cnt; - case IMGSENSOR_ID_ZOOM_ABSOLUTE: - sp->zoom = control->value; - break; + if (cmng == NULL || ctrls == NULL) + { + return -EINVAL; + } - case IMGSENSOR_ID_IRIS_ABSOLUTE: - sp->iris = control->value; - break; + ASSERT(cmng->imgsensor); - case IMGSENSOR_ID_AUTO_N_PRESET_WB: - sp->wb = control->value; - break; + for (cnt = 0, control = ctrls->controls; + cnt < ctrls->count; + cnt++, control++) + { + if (ctrls->ctrl_class == V4L2_CTRL_CLASS_CAMERA && + control->id == V4L2_CID_SCENE_MODE) + { + ret = reflect_scene_parameter(cmng, control->value); + } + else + { + ret = IMGSENSOR_SET_VALUE(cmng->imgsensor, + CAPTURE_ID(ctrls->ctrl_class, control->id), + control->size, + (imgsensor_value_t)control->value64); + if (ret == 0) + { + if (cmng->capture_scene_mode == V4L2_SCENE_MODE_NONE) + { + save_scene_param(cmng, V4L2_SCENE_MODE_NONE, + CAPTURE_ID(ctrls->ctrl_class, control->id), + control); + } + } + } - case IMGSENSOR_ID_WIDE_DYNAMIC_RANGE: - sp->wdr = control->value; - break; + if (ret < 0) + { + /* Set cnt in that error occurred */ - case IMGSENSOR_ID_IMG_STABILIZATION: - sp->stabilization = control->value; - break; + ctrls->error_idx = cnt; + return ret; + } + } - case IMGSENSOR_ID_ISO_SENSITIVITY: - sp->iso = control->value; - break; + return ret; +} - case IMGSENSOR_ID_ISO_SENSITIVITY_AUTO: - sp->iso_auto = control->value; - break; +static int capture_query_ext_ctrl_scene(FAR struct v4l2_s *v4l2, + FAR struct v4s_query_ext_ctrl_scene *attr) +{ + if (v4l2 == NULL || attr == NULL) + { + return -EINVAL; + } - case IMGSENSOR_ID_EXPOSURE_METERING: - sp->meter = control->value; - break; + return capture_query_ext_ctrl(v4l2, &attr->control); +} - case IMGSENSOR_ID_SPOT_POSITION: - sp->spot_pos = control->value; - break; +static int capture_querymenu_scene(FAR struct v4l2_s *v4l2, + FAR struct v4s_querymenu_scene *menu) +{ + if (v4l2 == NULL || menu == NULL) + { + return -EINVAL; + } - case IMGSENSOR_ID_3A_LOCK: - sp->threea_lock = control->value; - break; + return capture_querymenu(v4l2, &menu->menu); +} - case IMGSENSOR_ID_FLASH_LED_MODE: - sp->led = control->value; - break; +static int capture_s_ext_ctrls_scene(FAR struct v4l2_s *v4l2, + FAR struct v4s_ext_controls_scene *ctrls) +{ + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + FAR struct v4l2_ext_control *control; + int ret = OK; + int cnt; - case IMGSENSOR_ID_JPEG_QUALITY: - sp->jpeg_quality = control->value; - break; + if (cmng == NULL || ctrls == NULL) + { + return -EINVAL; + } - default: - return -EINVAL; + for (cnt = 0, control = ctrls->control.controls; + cnt < ctrls->control.count; + cnt++, control++) + { + ret = save_scene_param(cmng, ctrls->mode, + CAPTURE_ID(ctrls->control.ctrl_class, control->id), + control); + if (ret != OK) + { + ctrls->control.error_idx = cnt; + return ret; + } } - return OK; + return ret; } -static int video_s_ext_ctrls_scene(FAR struct video_mng_s *vmng, - FAR struct v4s_ext_controls_scene *ctrls) +static int capture_g_ext_ctrls_scene(FAR struct v4l2_s *v4l2, + FAR struct v4s_ext_controls_scene *ctrls) { + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; FAR struct v4l2_ext_control *control; int ret = OK; int cnt; - if (ctrls == NULL) + if (cmng == NULL || ctrls == NULL) { return -EINVAL; } @@ -3111,8 +3321,8 @@ static int video_s_ext_ctrls_scene(FAR struct video_mng_s *vmng, cnt < ctrls->control.count; cnt++, control++) { - ret = save_scene_param(vmng, ctrls->mode, - VIDEO_ID(ctrls->control.ctrl_class, control->id), + ret = read_scene_param(cmng, ctrls->mode, + CAPTURE_ID(ctrls->control.ctrl_class, control->id), control); if (ret != OK) { @@ -3124,26 +3334,36 @@ static int video_s_ext_ctrls_scene(FAR struct video_mng_s *vmng, return ret; } -static int video_enum_fmt(FAR video_mng_t *vmng, struct v4l2_fmtdesc *f) +static int capture_enum_fmt(FAR struct v4l2_s *v4l2, + FAR struct v4l2_fmtdesc *f) { - if (vmng->imgsensor && vmng->imgsensor->fmtdescs) + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + + if (cmng == NULL || f == NULL) + { + return -EINVAL; + } + + if (cmng->imgsensor && cmng->imgsensor->fmtdescs) { - if (f->index > vmng->imgsensor->fmtdescs_num) + if (f->index > cmng->imgsensor->fmtdescs_num) { return -EINVAL; } else { - f->pixelformat = vmng->imgsensor->fmtdescs[f->index].pixelformat; + f->pixelformat = cmng->imgsensor->fmtdescs[f->index].pixelformat; strlcpy(f->description, - vmng->imgsensor->fmtdescs[f->index].description, + cmng->imgsensor->fmtdescs[f->index].description, sizeof(f->description)); } } else { if (f->index > 0) + { return -EINVAL; + } f->pixelformat = V4L2_PIX_FMT_UYVY; } @@ -3151,32 +3371,41 @@ static int video_enum_fmt(FAR video_mng_t *vmng, struct v4l2_fmtdesc *f) return 0; } -static int video_enum_frmsize(FAR video_mng_t *vmng, - struct v4l2_frmsizeenum *f) +static int capture_enum_frmsize(FAR struct v4l2_s *v4l2, + FAR struct v4l2_frmsizeenum *f) { - if (vmng->imgsensor && vmng->imgsensor->frmsizes) + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + + if (cmng == NULL || f == NULL) + { + return -EINVAL; + } + + if (cmng->imgsensor && cmng->imgsensor->frmsizes) { - if (f->index > vmng->imgsensor->frmsizes_num) + if (f->index > cmng->imgsensor->frmsizes_num) { return -EINVAL; } else { - f->type = vmng->imgsensor->frmsizes[f->index].type; + f->type = cmng->imgsensor->frmsizes[f->index].type; if (f->type == V4L2_FRMSIZE_TYPE_DISCRETE) { - f->discrete = vmng->imgsensor->frmsizes[f->index].discrete; + f->discrete = cmng->imgsensor->frmsizes[f->index].discrete; } else { - f->stepwise = vmng->imgsensor->frmsizes[f->index].stepwise; + f->stepwise = cmng->imgsensor->frmsizes[f->index].stepwise; } } } else { if (f->index > 0) + { return -EINVAL; + } f->type = V4L2_FRMIVAL_TYPE_DISCRETE; f->discrete.width = VIDEO_HSIZE_QVGA; @@ -3186,32 +3415,41 @@ static int video_enum_frmsize(FAR video_mng_t *vmng, return 0; } -static int video_enum_frminterval(FAR video_mng_t *vmng, - struct v4l2_frmivalenum *f) +static int capture_enum_frminterval(FAR struct v4l2_s *v4l2, + FAR struct v4l2_frmivalenum *f) { - if (vmng->imgsensor && vmng->imgsensor->frmintervals) + FAR capture_mng_t *cmng = (FAR capture_mng_t *)v4l2; + + if (cmng == NULL || f == NULL) + { + return -EINVAL; + } + + if (cmng->imgsensor && cmng->imgsensor->frmintervals) { - if (f->index > vmng->imgsensor->frmintervals_num) + if (f->index > cmng->imgsensor->frmintervals_num) { return -EINVAL; } else { - f->type = vmng->imgsensor->frmintervals[f->index].type; + f->type = cmng->imgsensor->frmintervals[f->index].type; if (f->type == V4L2_FRMIVAL_TYPE_DISCRETE) { - f->discrete = vmng->imgsensor->frmintervals[f->index].discrete; + f->discrete = cmng->imgsensor->frmintervals[f->index].discrete; } else { - f->stepwise = vmng->imgsensor->frmintervals[f->index].stepwise; + f->stepwise = cmng->imgsensor->frmintervals[f->index].stepwise; } } } else { if (f->index > 0) + { return -EINVAL; + } f->type = V4L2_FRMIVAL_TYPE_DISCRETE; f->discrete.denominator = 15; @@ -3222,191 +3460,101 @@ static int video_enum_frminterval(FAR video_mng_t *vmng, } /**************************************************************************** - * Name: video_ioctl - * - * Description: - * Standard character driver ioctl method. - * + * File Opterations Functions ****************************************************************************/ -static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +static int capture_open(FAR struct file *filep) { FAR struct inode *inode = filep->f_inode; - FAR video_mng_t *priv = inode->i_private; + FAR capture_mng_t *cmng = inode->i_private; int ret = OK; - switch (cmd) + if (cmng == NULL) { - case VIDIOC_QUERYCAP: - ret = video_querycap(priv, (FAR struct v4l2_capability *)arg); - break; - - case VIDIOC_G_INPUT: - ret = video_g_input((FAR int *)arg); - break; - - case VIDIOC_ENUMINPUT: - ret = video_enum_input(priv, (FAR struct v4l2_input *)arg); - break; - - case VIDIOC_REQBUFS: - ret = video_reqbufs(priv, (FAR struct v4l2_requestbuffers *)arg); - break; - - case VIDIOC_QUERYBUF: - ret = video_querybuf(priv, (FAR struct v4l2_buffer *)arg); - - break; - - case VIDIOC_QBUF: - ret = video_qbuf(priv, (FAR struct v4l2_buffer *)arg); - break; - - case VIDIOC_DQBUF: - ret = video_dqbuf(priv, (FAR struct v4l2_buffer *)arg, - filep->f_oflags); - break; - - case VIDIOC_CANCEL_DQBUF: - ret = video_cancel_dqbuf(priv, (FAR enum v4l2_buf_type)arg); - break; - - case VIDIOC_STREAMON: - ret = video_streamon(priv, (FAR enum v4l2_buf_type *)arg); - break; - - case VIDIOC_STREAMOFF: - ret = video_streamoff(priv, (FAR enum v4l2_buf_type *)arg); - break; - - case VIDIOC_DO_HALFPUSH: - ret = video_do_halfpush(priv, arg); - break; - - case VIDIOC_TAKEPICT_START: - ret = video_takepict_start(priv, (int32_t)arg); - break; - - case VIDIOC_TAKEPICT_STOP: - ret = video_takepict_stop(priv, arg); - break; - - case VIDIOC_S_SELECTION: - ret = video_s_selection(priv, (FAR struct v4l2_selection *)arg); - break; - - case VIDIOC_G_SELECTION: - ret = video_g_selection(priv, (FAR struct v4l2_selection *)arg); - break; - - case VIDIOC_TRY_FMT: - ret = video_try_fmt(priv, (FAR struct v4l2_format *)arg); - break; - - case VIDIOC_G_FMT: - ret = video_g_fmt(priv, (FAR struct v4l2_format *)arg); - break; - - case VIDIOC_S_FMT: - ret = video_s_fmt(priv, (FAR struct v4l2_format *)arg); - break; - - case VIDIOC_S_PARM: - ret = video_s_parm(priv, (FAR struct v4l2_streamparm *)arg); - break; - - case VIDIOC_G_PARM: - ret = video_g_parm(priv, (FAR struct v4l2_streamparm *)arg); - break; - - case VIDIOC_QUERYCTRL: - ret = video_queryctrl(priv, (FAR struct v4l2_queryctrl *)arg); - break; - - case VIDIOC_QUERY_EXT_CTRL: - ret = video_query_ext_ctrl(priv, - (FAR struct v4l2_query_ext_ctrl *)arg); - break; - - case VIDIOC_QUERYMENU: - ret = video_querymenu(priv, (FAR struct v4l2_querymenu *)arg); - break; - - case VIDIOC_G_CTRL: - ret = video_g_ctrl(priv, (FAR struct v4l2_control *)arg); - break; - - case VIDIOC_S_CTRL: - ret = video_s_ctrl(priv, (FAR struct v4l2_control *)arg); - break; - - case VIDIOC_G_EXT_CTRLS: - ret = video_g_ext_ctrls(priv, (FAR struct v4l2_ext_controls *)arg); - break; - - case VIDIOC_S_EXT_CTRLS: - ret = video_s_ext_ctrls(priv, (FAR struct v4l2_ext_controls *)arg); - break; + return -EINVAL; + } - case VIDIOC_G_STD: - ret = -ENODATA; - break; + nxmutex_lock(&cmng->lock_open_num); + if (cmng->open_num == 0) + { + /* Only in first execution, open device */ - case VIDIOC_S_STD: - ret = -EINVAL; - break; + ret = IMGSENSOR_INIT(cmng->imgsensor); + if (ret == OK) + { + ret = IMGDATA_INIT(cmng->imgdata); + if (ret == OK) + { + initialize_resources(cmng); + } + } + else + { + ret = -ENODEV; + } + } - case V4SIOC_QUERY_EXT_CTRL_SCENE: - ret = video_query_ext_ctrl_scene(priv, - (FAR struct v4s_query_ext_ctrl_scene *)arg); - break; + /* In second or later execution, ret is initial value(=OK) */ - case V4SIOC_QUERYMENU_SCENE: - ret = video_querymenu_scene(priv, - (FAR struct v4s_querymenu_scene *)arg); - break; + if (ret == OK) + { + cmng->open_num++; + } - case V4SIOC_G_EXT_CTRLS_SCENE: - ret = video_g_ext_ctrls_scene(priv, - (FAR struct v4s_ext_controls_scene *)arg); - break; + nxmutex_unlock(&cmng->lock_open_num); + return ret; +} - case V4SIOC_S_EXT_CTRLS_SCENE: - ret = video_s_ext_ctrls_scene(priv, - (FAR struct v4s_ext_controls_scene *)arg); - break; +static int capture_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR capture_mng_t *cmng = inode->i_private; - case VIDIOC_ENUM_FMT: - ret = video_enum_fmt(priv, - (FAR struct v4l2_fmtdesc *)arg); - break; + if (cmng == NULL) + { + return -EINVAL; + } - case VIDIOC_ENUM_FRAMEINTERVALS: - ret = video_enum_frminterval(priv, - (FAR struct v4l2_frmivalenum *)arg); - break; + nxmutex_lock(&cmng->lock_open_num); - case VIDIOC_ENUM_FRAMESIZES: - ret = video_enum_frmsize(priv, - (FAR struct v4l2_frmsizeenum *)arg); - break; + if (--cmng->open_num == 0) + { + cleanup_resources(cmng); + IMGSENSOR_UNINIT(cmng->imgsensor); + IMGDATA_UNINIT(cmng->imgdata); +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + if (cmng->unlinked) + { + nxmutex_unlock(&cmng->lock_open_num); + nxmutex_destroy(&cmng->lock_open_num); + kmm_free(cmng); + inode->i_private = NULL; + return OK; + } - default: - verr("Unrecognized cmd: %d\n", cmd); - ret = - ENOTTY; - break; +#endif } - return ret; + nxmutex_unlock(&cmng->lock_open_num); + return OK; } -static int video_mmap(FAR struct file *filep, FAR struct mm_map_entry_s *map) +static int capture_mmap(FAR struct file *filep, + FAR struct mm_map_entry_s *map) { - FAR struct inode *inode = filep->f_inode; - FAR video_mng_t *priv = inode->i_private; - FAR video_type_inf_t *type_inf = &priv->video_inf; - size_t heapsize = get_heapsize(type_inf); - int ret = -EINVAL; + FAR struct inode *inode = filep->f_inode; + FAR capture_mng_t *cmng = inode->i_private; + FAR capture_type_inf_t *type_inf; + size_t heapsize; + int ret = -EINVAL; + + if (cmng == NULL) + { + return -EINVAL; + } + + type_inf = &cmng->capture_inf; + heapsize = get_heapsize(type_inf); if (map->offset >= 0 && map->offset < heapsize && map->length && map->offset + map->length <= heapsize) @@ -3418,18 +3566,24 @@ static int video_mmap(FAR struct file *filep, FAR struct mm_map_entry_s *map) return ret; } -static int video_poll(FAR struct file *filep, struct pollfd *fds, bool setup) +static int capture_poll(FAR struct file *filep, + struct pollfd *fds, bool setup) { - FAR struct inode *inode = filep->f_inode; - FAR video_mng_t *priv = inode->i_private; - FAR video_type_inf_t *type_inf; - enum v4l2_buf_type buf_type; - irqstate_t flags; + FAR struct inode *inode = filep->f_inode; + FAR capture_mng_t *cmng = inode->i_private; + FAR capture_type_inf_t *type_inf; + enum v4l2_buf_type buf_type; + irqstate_t flags; + + if (cmng == NULL) + { + return -EINVAL; + } - buf_type = priv->still_inf.state == VIDEO_STATE_CAPTURE ? - V4L2_BUF_TYPE_STILL_CAPTURE : V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf_type = cmng->still_inf.state == CAPTURE_STATE_CAPTURE ? + V4L2_BUF_TYPE_STILL_CAPTURE : V4L2_BUF_TYPE_VIDEO_CAPTURE; - type_inf = get_video_type_inf(priv, buf_type); + type_inf = get_capture_type_inf(cmng, buf_type); if (type_inf == NULL) { return -EINVAL; @@ -3465,140 +3619,60 @@ static int video_poll(FAR struct file *filep, struct pollfd *fds, bool setup) return OK; } -/* Callback function which device driver call when capture has done. */ - -static int video_complete_capture(uint8_t err_code, uint32_t datasize, - FAR const struct timeval *ts, - FAR void *arg) +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int capture_unlink(FAR struct inode *inode) { - FAR video_mng_t *vmng = (FAR video_mng_t *)arg; - FAR video_type_inf_t *type_inf; - FAR vbuf_container_t *container = NULL; - enum v4l2_buf_type buf_type; - irqstate_t flags; - imgdata_format_t df[MAX_VIDEO_FMT]; - video_format_t c_fmt[MAX_VIDEO_FMT]; - - flags = enter_critical_section(); + FAR capture_mng_t *cmng = inode->i_private; - buf_type = vmng->still_inf.state == VIDEO_STATE_CAPTURE ? - V4L2_BUF_TYPE_STILL_CAPTURE : V4L2_BUF_TYPE_VIDEO_CAPTURE; - - type_inf = get_video_type_inf(vmng, buf_type); - if (type_inf == NULL) + if (cmng == NULL) { - leave_critical_section(flags); return -EINVAL; } - poll_notify(&type_inf->fds, 1, POLLIN); - - if (err_code == 0) + nxmutex_lock(&cmng->lock_open_num); + if (cmng->open_num == 0) { - type_inf->bufinf.vbuf_curr->buf.flags = 0; - if (type_inf->remaining_capnum > 0) - { - type_inf->remaining_capnum--; - } + nxmutex_unlock(&cmng->lock_open_num); + nxmutex_destroy(&cmng->lock_open_num); + kmm_free(cmng); + inode->i_private = NULL; } else { - type_inf->bufinf.vbuf_curr->buf.flags = V4L2_BUF_FLAG_ERROR; - } - - type_inf->bufinf.vbuf_curr->buf.bytesused = datasize; - if (ts != NULL) - { - type_inf->bufinf.vbuf_curr->buf.timestamp = *ts; - } - - video_framebuff_capture_done(&type_inf->bufinf); - - if (is_sem_waited(&type_inf->wait_capture.dqbuf_wait_flg)) - { - /* If waiting capture in DQBUF, - * get/save container and unlock wait - */ - - type_inf->wait_capture.done_container = - video_framebuff_pop_curr_container(&type_inf->bufinf); - type_inf->wait_capture.waitend_cause = - VIDEO_WAITEND_CAUSE_CAPTUREDONE; - nxsem_post(&type_inf->wait_capture.dqbuf_wait_flg); + cmng->unlinked = true; + nxmutex_unlock(&cmng->lock_open_num); } - if (type_inf->remaining_capnum == 0) - { - stop_capture(vmng, buf_type); - type_inf->state = VIDEO_STATE_STREAMOFF; - - /* If stop still stream, notify it to video stream */ - - if (buf_type == V4L2_BUF_TYPE_STILL_CAPTURE && - is_sem_waited(&vmng->video_inf.wait_capture.dqbuf_wait_flg)) - { - vmng->video_inf.wait_capture.waitend_cause = - VIDEO_WAITEND_CAUSE_STILLSTOP; - nxsem_post(&vmng->video_inf.wait_capture.dqbuf_wait_flg); - } - } - else - { - container = video_framebuff_get_vacant_container(&type_inf->bufinf); - if (container == NULL) - { - stop_capture(vmng, buf_type); - type_inf->state = VIDEO_STATE_STREAMON; - } - else - { - get_clipped_format(type_inf->nr_fmt, - type_inf->fmt, - &type_inf->clip, - c_fmt); - - convert_to_imgdatafmt(&c_fmt[VIDEO_FMT_MAIN], - &df[IMGDATA_FMT_MAIN]); - convert_to_imgdatafmt(&c_fmt[VIDEO_FMT_SUB], &df[IMGDATA_FMT_SUB]); - - IMGDATA_SET_BUF(vmng->imgdata, - type_inf->nr_fmt, - df, - (FAR uint8_t *)container->buf.m.userptr, - container->buf.length); - container->buf.sequence = type_inf->seqnum++; - } - } + nxmutex_destroy(&cmng->lock_open_num); - leave_critical_section(flags); return OK; } +#endif /**************************************************************************** * Public Functions ****************************************************************************/ -int video_initialize(FAR const char *devpath) +int capture_initialize(FAR const char *devpath) { - return video_register(devpath, - g_video_data, - g_video_registered_sensor, - g_video_registered_sensor_num); + return capture_register(devpath, + g_capture_data, + g_capture_registered_sensor, + g_capture_registered_sensor_num); } -int video_uninitialize(FAR const char *devpath) +int capture_uninitialize(FAR const char *devpath) { - return video_unregister(devpath); + return capture_unregister(devpath); } -int video_register(FAR const char *devpath, - FAR struct imgdata_s *data, - FAR struct imgsensor_s **sensors, - size_t sensor_num) +int capture_register(FAR const char *devpath, + FAR struct imgdata_s *data, + FAR struct imgsensor_s **sensors, + size_t sensor_num) { - FAR video_mng_t *priv; - size_t allocsize; - int ret; + FAR capture_mng_t *cmng; + int ret; /* Input devpath Error Check */ @@ -3607,64 +3681,45 @@ int video_register(FAR const char *devpath, return -EINVAL; } - allocsize = strnlen(devpath, MAX_VIDEO_FILE_PATH - 1/* Space for '\0' */); - if (allocsize < 2 || - devpath[0] != '/' || - (allocsize == MAX_VIDEO_FILE_PATH - 1 && - devpath[MAX_VIDEO_FILE_PATH] != '\0')) - { - return -EINVAL; - } - - /* Initialize video device structure */ + /* Initialize capture device structure */ - priv = kmm_zalloc(sizeof(video_mng_t)); - if (priv == NULL) + cmng = kmm_zalloc(sizeof(capture_mng_t)); + if (cmng == NULL) { verr("Failed to allocate instance\n"); return -ENOMEM; } - priv->imgsensor = get_connected_imgsensor(sensors, sensor_num); - if (priv->imgsensor == NULL) - { - kmm_free(priv); - return -EINVAL; - } - - /* Save device path */ + cmng->v4l2.vops = &g_capture_vops; + cmng->v4l2.fops = &g_capture_fops; - priv->devpath = kmm_malloc(allocsize + 1); - if (priv->devpath == NULL) + cmng->imgdata = data; + cmng->imgsensor = get_connected_imgsensor(sensors, sensor_num); + if (cmng->imgsensor == NULL) { - kmm_free(priv); - return -ENOMEM; + kmm_free(cmng); + return -EINVAL; } - memcpy(priv->devpath, devpath, allocsize); - priv->devpath[allocsize] = '\0'; - priv->imgdata = data; - /* Initialize mutex */ - nxmutex_init(&priv->lock_open_num); + nxmutex_init(&cmng->lock_open_num); /* Register the character driver */ - ret = register_driver(priv->devpath, &g_video_fops, 0666, priv); + ret = video_register(devpath, (FAR struct v4l2_s *)cmng); if (ret < 0) { verr("Failed to register driver: %d\n", ret); - nxmutex_destroy(&priv->lock_open_num); - kmm_free(priv->devpath); - kmm_free(priv); + nxmutex_destroy(&cmng->lock_open_num); + kmm_free(cmng); return ret; } return OK; } -int video_unregister(FAR const char *devpath) +int capture_unregister(FAR const char *devpath) { return unregister_driver(devpath); } @@ -3674,12 +3729,12 @@ int imgsensor_register(FAR struct imgsensor_s *sensor) FAR struct imgsensor_s **new_addr; int ret = -ENOMEM; - new_addr = kmm_realloc(g_video_registered_sensor, sizeof(sensor) * - (g_video_registered_sensor_num + 1)); + new_addr = kmm_realloc(g_capture_registered_sensor, sizeof(sensor) * + (g_capture_registered_sensor_num + 1)); if (new_addr != NULL) { - new_addr[g_video_registered_sensor_num++] = sensor; - g_video_registered_sensor = new_addr; + new_addr[g_capture_registered_sensor_num++] = sensor; + g_capture_registered_sensor = new_addr; ret = OK; } @@ -3688,5 +3743,5 @@ int imgsensor_register(FAR struct imgsensor_s *sensor) void imgdata_register(FAR struct imgdata_s *data) { - g_video_data = data; + g_capture_data = data; } diff --git a/drivers/video/v4l2_core.c b/drivers/video/v4l2_core.c new file mode 100644 index 0000000000000..1fc5927158cf6 --- /dev/null +++ b/drivers/video/v4l2_core.c @@ -0,0 +1,533 @@ +/**************************************************************************** + * drivers/video/v4l2_core.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Character driver methods. */ + +static int v4l2_open(FAR struct file *filep); +static int v4l2_close(FAR struct file *filep); +static ssize_t v4l2_read(FAR struct file *filep, + FAR char *buffer, size_t buflen); +static ssize_t v4l2_write(FAR struct file *filep, + FAR const char *buffer, size_t buflen); +static int v4l2_ioctl(FAR struct file *filep, + int cmd, unsigned long arg); +static int v4l2_mmap(FAR struct file *filep, + FAR struct mm_map_entry_s *map); +static int v4l2_poll(FAR struct file *filep, + FAR struct pollfd *fds, bool setup); +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int v4l2_unlink(FAR struct inode *inode); +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +static const struct file_operations g_v4l2_fops = +{ + v4l2_open, /* open */ + v4l2_close, /* close */ + v4l2_read, /* read */ + v4l2_write, /* write */ + NULL, /* seek */ + v4l2_ioctl, /* ioctl */ + v4l2_mmap, /* mmap */ + NULL, /* truncate */ + v4l2_poll, /* poll */ +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + v4l2_unlink, /* unlink */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int v4l2_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct v4l2_s *v4l2 = inode->i_private; + + if (v4l2->fops->open != NULL) + { + return v4l2->fops->open(filep); + } + + return -ENOTSUP; +} + +static int v4l2_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct v4l2_s *v4l2 = inode->i_private; + + if (v4l2->fops->close != NULL) + { + return v4l2->fops->close(filep); + } + + return -ENOTSUP; +} + +static ssize_t v4l2_read(FAR struct file *filep, + FAR char *buffer, size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct v4l2_s *v4l2 = inode->i_private; + + if (v4l2->fops->read != NULL) + { + return v4l2->fops->read(filep, buffer, buflen); + } + + return -ENOTSUP; +} + +static ssize_t v4l2_write(FAR struct file *filep, + FAR const char *buffer, size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct v4l2_s *v4l2 = inode->i_private; + + if (v4l2->fops->write != NULL) + { + return v4l2->fops->write(filep, buffer, buflen); + } + + return -ENOTSUP; +} + +static int v4l2_ioctl(FAR struct file *filep, + int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct v4l2_s *v4l2 = inode->i_private; + + switch (cmd) + { + case VIDIOC_QUERYCAP: + if (v4l2->vops->querycap == NULL) + { + break; + } + + return v4l2->vops->querycap(v4l2, + (FAR struct v4l2_capability *)arg); + + case VIDIOC_G_INPUT: + if (v4l2->vops->g_input == NULL) + { + break; + } + + return v4l2->vops->g_input((FAR int *)arg); + + case VIDIOC_ENUMINPUT: + if (v4l2->vops->enum_input == NULL) + { + break; + } + + return v4l2->vops->enum_input(v4l2, + (FAR struct v4l2_input *)arg); + + case VIDIOC_REQBUFS: + if (v4l2->vops->reqbufs == NULL) + { + break; + } + + return v4l2->vops->reqbufs(v4l2, + (FAR struct v4l2_requestbuffers *)arg); + + case VIDIOC_QUERYBUF: + if (v4l2->vops->querybuf == NULL) + { + break; + } + + return v4l2->vops->querybuf(v4l2, + (FAR struct v4l2_buffer *)arg); + + case VIDIOC_QBUF: + if (v4l2->vops->qbuf == NULL) + { + break; + } + + return v4l2->vops->qbuf(v4l2, + (FAR struct v4l2_buffer *)arg); + break; + + case VIDIOC_DQBUF: + if (v4l2->vops->dqbuf == NULL) + { + break; + } + + return v4l2->vops->dqbuf(v4l2, + (FAR struct v4l2_buffer *)arg, + filep->f_oflags); + + case VIDIOC_CANCEL_DQBUF: + if (v4l2->vops->cancel_dqbuf == NULL) + { + break; + } + + return v4l2->vops->cancel_dqbuf(v4l2, + (FAR enum v4l2_buf_type)arg); + + case VIDIOC_STREAMON: + if (v4l2->vops->streamon == NULL) + { + break; + } + + return v4l2->vops->streamon(v4l2, + (FAR enum v4l2_buf_type *)arg); + + case VIDIOC_STREAMOFF: + if (v4l2->vops->streamoff == NULL) + { + break; + } + + return v4l2->vops->streamoff(v4l2, + (FAR enum v4l2_buf_type *)arg); + + case VIDIOC_DO_HALFPUSH: + if (v4l2->vops->do_halfpush == NULL) + { + break; + } + + return v4l2->vops->do_halfpush(v4l2, arg); + + case VIDIOC_TAKEPICT_START: + if (v4l2->vops->takepict_start == NULL) + { + break; + } + + return v4l2->vops->takepict_start(v4l2, (int32_t)arg); + + case VIDIOC_TAKEPICT_STOP: + if (v4l2->vops->takepict_stop == NULL) + { + break; + } + + return v4l2->vops->takepict_stop(v4l2, arg); + + case VIDIOC_S_SELECTION: + if (v4l2->vops->s_selection == NULL) + { + break; + } + + return v4l2->vops->s_selection(v4l2, + (FAR struct v4l2_selection *)arg); + + case VIDIOC_G_SELECTION: + if (v4l2->vops->g_selection == NULL) + { + break; + } + + return v4l2->vops->g_selection(v4l2, + (FAR struct v4l2_selection *)arg); + + case VIDIOC_TRY_FMT: + if (v4l2->vops->try_fmt == NULL) + { + break; + } + + return v4l2->vops->try_fmt(v4l2, + (FAR struct v4l2_format *)arg); + + case VIDIOC_G_FMT: + if (v4l2->vops->g_fmt == NULL) + { + break; + } + + return v4l2->vops->g_fmt(v4l2, + (FAR struct v4l2_format *)arg); + + case VIDIOC_S_FMT: + if (v4l2->vops->s_fmt == NULL) + { + break; + } + + return v4l2->vops->s_fmt(v4l2, + (FAR struct v4l2_format *)arg); + + case VIDIOC_S_PARM: + if (v4l2->vops->s_parm == NULL) + { + break; + } + + return v4l2->vops->s_parm(v4l2, + (FAR struct v4l2_streamparm *)arg); + + case VIDIOC_G_PARM: + if (v4l2->vops->g_parm == NULL) + { + break; + } + + return v4l2->vops->g_parm(v4l2, + (FAR struct v4l2_streamparm *)arg); + + case VIDIOC_QUERYCTRL: + if (v4l2->vops->queryctrl == NULL) + { + break; + } + + return v4l2->vops->queryctrl(v4l2, + (FAR struct v4l2_queryctrl *)arg); + + case VIDIOC_QUERY_EXT_CTRL: + if (v4l2->vops->query_ext_ctrl == NULL) + { + break; + } + + return v4l2->vops->query_ext_ctrl(v4l2, + (FAR struct v4l2_query_ext_ctrl *)arg); + + case VIDIOC_QUERYMENU: + if (v4l2->vops->querymenu == NULL) + { + break; + } + + return v4l2->vops->querymenu(v4l2, + (FAR struct v4l2_querymenu *)arg); + + case VIDIOC_G_CTRL: + if (v4l2->vops->g_ctrl == NULL) + { + break; + } + + return v4l2->vops->g_ctrl(v4l2, + (FAR struct v4l2_control *)arg); + + case VIDIOC_S_CTRL: + if (v4l2->vops->s_ctrl == NULL) + { + break; + } + + return v4l2->vops->s_ctrl(v4l2, + (FAR struct v4l2_control *)arg); + + case VIDIOC_G_EXT_CTRLS: + if (v4l2->vops->g_ext_ctrls == NULL) + { + break; + } + + return v4l2->vops->g_ext_ctrls(v4l2, + (FAR struct v4l2_ext_controls *)arg); + + case VIDIOC_S_EXT_CTRLS: + if (v4l2->vops->s_ext_ctrls == NULL) + { + break; + } + + return v4l2->vops->s_ext_ctrls(v4l2, + (FAR struct v4l2_ext_controls *)arg); + + case VIDIOC_G_STD: + break; + + case VIDIOC_S_STD: + break; + + case V4SIOC_QUERY_EXT_CTRL_SCENE: + if (v4l2->vops->query_ext_ctrl_scene == NULL) + { + break; + } + + return v4l2->vops->query_ext_ctrl_scene(v4l2, + (FAR struct v4s_query_ext_ctrl_scene *)arg); + + case V4SIOC_QUERYMENU_SCENE: + if (v4l2->vops->querymenu_scene == NULL) + { + break; + } + + return v4l2->vops->querymenu_scene(v4l2, + (FAR struct v4s_querymenu_scene *)arg); + + case V4SIOC_G_EXT_CTRLS_SCENE: + if (v4l2->vops->g_ext_ctrls_scene == NULL) + { + break; + } + + return v4l2->vops->g_ext_ctrls_scene(v4l2, + (FAR struct v4s_ext_controls_scene *)arg); + + case V4SIOC_S_EXT_CTRLS_SCENE: + if (v4l2->vops->s_ext_ctrls_scene == NULL) + { + break; + } + + return v4l2->vops->s_ext_ctrls_scene(v4l2, + (FAR struct v4s_ext_controls_scene *)arg); + + case VIDIOC_ENUM_FMT: + if (v4l2->vops->enum_fmt == NULL) + { + break; + } + + return v4l2->vops->enum_fmt(v4l2, + (FAR struct v4l2_fmtdesc *)arg); + break; + + case VIDIOC_ENUM_FRAMEINTERVALS: + if (v4l2->vops->enum_frminterval == NULL) + { + break; + } + + return v4l2->vops->enum_frminterval(v4l2, + (FAR struct v4l2_frmivalenum *)arg); + break; + + case VIDIOC_ENUM_FRAMESIZES: + if (v4l2->vops->enum_frmsize == NULL) + { + break; + } + + return v4l2->vops->enum_frmsize(v4l2, + (FAR struct v4l2_frmsizeenum *)arg); + break; + + default: + verr("Unrecognized cmd: %d\n", cmd); + break; + } + + return -ENOTTY; +} + +static int v4l2_mmap(FAR struct file *filep, + FAR struct mm_map_entry_s *map) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct v4l2_s *v4l2 = inode->i_private; + + if (v4l2->fops->mmap != NULL) + { + return v4l2->fops->mmap(filep, map); + } + + return -ENOTSUP; +} + +static int v4l2_poll(FAR struct file *filep, + FAR struct pollfd *fds, bool setup) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct v4l2_s *v4l2 = inode->i_private; + + if (v4l2->fops->poll != NULL) + { + return v4l2->fops->poll(filep, fds, setup); + } + + return -ENOTSUP; +} + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int v4l2_unlink(FAR struct inode *inode) +{ + FAR struct v4l2_s *v4l2 = inode->i_private; + + if (v4l2->fops->unlink != NULL) + { + return v4l2->fops->unlink(inode); + } + + return -ENOTSUP; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int video_register(FAR const char *devpath, FAR struct v4l2_s *v4l2) +{ + int ret; + + /* Input devpath Error Check */ + + if (devpath[0] != '/') + { + return -EINVAL; + } + + /* Register the character driver */ + + ret = register_driver(devpath, &g_v4l2_fops, 0666, v4l2); + if (ret < 0) + { + verr("Failed to register driver: %d\n", ret); + return ret; + } + + return OK; +} + +int video_unregister(FAR const char *devpath) +{ + return unregister_driver(devpath); +} + diff --git a/include/nuttx/video/v4l2_cap.h b/include/nuttx/video/v4l2_cap.h new file mode 100644 index 0000000000000..ead917eb29b04 --- /dev/null +++ b/include/nuttx/video/v4l2_cap.h @@ -0,0 +1,87 @@ +/**************************************************************************** + * include/nuttx/video/v4l2_cap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + ****************************************************************************/ + +#ifndef __NUTTX_VIDEO_V4L2_CAP_H +#define __NUTTX_VIDEO_V4L2_CAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Initialize capture driver. + * + * param [in] devpath: path to capture device + * + * Return on success, 0 is returned. On failure, + * negative value is returned. + */ + +int capture_initialize(FAR const char *devpath); + +/* Uninitialize capture driver. + * + * Return on success, 0 is returned. On failure, + * negative value is returned. + */ + +int capture_uninitialize(FAR const char *devpath); + +/* New API to register capture driver. + * + * param [in] devpath: path to capture device + * param [in] data: provide imgdata ops + * param [in] sensor: provide imgsensor ops array + * param [in] sensor_num: the number of imgsensor ops array + * + * Return on success, 0 is returned. On failure, + * negative value is returned. + */ + +int capture_register(FAR const char *devpath, + FAR struct imgdata_s *data, + FAR struct imgsensor_s **sensors, + size_t sensor_num); + +/* New API to Unregister capture driver. + * + * param [in] devpath: path to capture device + * + * Return on success, 0 is returned. On failure, + * negative value is returned. + */ + +int capture_unregister(FAR const char *devpath); + +#ifdef __cplusplus +} +#endif + +#endif /* __NUTTX_VIDEO_V4L2_CAP_H */ diff --git a/include/nuttx/video/video.h b/include/nuttx/video/video.h index 0b035318dad43..3ea45a424f31b 100644 --- a/include/nuttx/video/video.h +++ b/include/nuttx/video/video.h @@ -30,6 +30,7 @@ ****************************************************************************/ #include +#include #ifdef __cplusplus extern "C" @@ -56,29 +57,98 @@ extern "C" #define VIDEO_VSIZE_3M (1536) /* 3M vertical size */ /**************************************************************************** - * Public Function Prototypes - ****************************************************************************/ +* Public Types +*****************************************************************************/ -struct imgdata_s; -struct imgsensor_s; +struct video_format_s +{ + uint16_t width; + uint16_t height; + uint32_t pixelformat; +}; -/* Initialize video driver. - * - * param [in] devpath: path to video device - * - * Return on success, 0 is returned. On failure, - * negative value is returned. - */ +typedef struct video_format_s video_format_t; -int video_initialize(FAR const char *devpath); +struct v4l2_s +{ + FAR const struct v4l2_ops_s *vops; + FAR const struct file_operations *fops; +}; -/* Uninitialize video driver. - * - * Return on success, 0 is returned. On failure, - * negative value is returned. - */ +struct v4l2_ops_s +{ + CODE int (*querycap)(FAR struct v4l2_s *ctx, + FAR struct v4l2_capability *cap); + CODE int (*g_input)(FAR int *num); + CODE int (*enum_input)(FAR struct v4l2_s *ctx, + FAR struct v4l2_input *input); + CODE int (*reqbufs)(FAR struct v4l2_s *ctx, + FAR struct v4l2_requestbuffers *reqbufs); + CODE int (*querybuf)(FAR struct v4l2_s *ctx, + FAR struct v4l2_buffer *buf); + CODE int (*qbuf)(FAR struct v4l2_s *ctx, + FAR struct v4l2_buffer *buf); + CODE int (*dqbuf)(FAR struct v4l2_s *ctx, + FAR struct v4l2_buffer *buf, int oflags); + CODE int (*cancel_dqbuf)(FAR struct v4l2_s *ctx, + enum v4l2_buf_type type); + CODE int (*g_fmt)(FAR struct v4l2_s *ctx, + FAR struct v4l2_format *fmt); + CODE int (*s_fmt)(FAR struct v4l2_s *ctx, + FAR struct v4l2_format *fmt); + CODE int (*try_fmt)(FAR struct v4l2_s *ctx, + FAR struct v4l2_format *v4l2); + CODE int (*g_parm)(FAR struct v4l2_s *ctx, + FAR struct v4l2_streamparm *parm); + CODE int (*s_parm)(FAR struct v4l2_s *ctx, + FAR struct v4l2_streamparm *parm); + CODE int (*streamon)(FAR struct v4l2_s *ctx, + FAR enum v4l2_buf_type *type); + CODE int (*streamoff)(FAR struct v4l2_s *ctx, + FAR enum v4l2_buf_type *type); + CODE int (*do_halfpush)(FAR struct v4l2_s *ctx, + bool enable); + CODE int (*takepict_start)(FAR struct v4l2_s *ctx, + int32_t capture_num); + CODE int (*takepict_stop)(FAR struct v4l2_s *ctx, + bool halfpush); + CODE int (*s_selection)(FAR struct v4l2_s *ctx, + FAR struct v4l2_selection *clip); + CODE int (*g_selection)(FAR struct v4l2_s *ctx, + FAR struct v4l2_selection *clip); + CODE int (*queryctrl)(FAR struct v4l2_s *ctx, + FAR struct v4l2_queryctrl *ctrl); + CODE int (*query_ext_ctrl)(FAR struct v4l2_s *ctx, + FAR struct v4l2_query_ext_ctrl *ctrl); + CODE int (*querymenu)(FAR struct v4l2_s *ctx, + FAR struct v4l2_querymenu *menu); + CODE int (*g_ctrl)(FAR struct v4l2_s *ctx, + FAR struct v4l2_control *ctrl); + CODE int (*s_ctrl)(FAR struct v4l2_s *ctx, + FAR struct v4l2_control *ctrl); + CODE int (*g_ext_ctrls)(FAR struct v4l2_s *ctx, + FAR struct v4l2_ext_controls *ctrls); + CODE int (*s_ext_ctrls)(FAR struct v4l2_s *ctx, + FAR struct v4l2_ext_controls *ctrls); + CODE int (*query_ext_ctrl_scene)(FAR struct v4l2_s *ctx, + FAR struct v4s_query_ext_ctrl_scene *ctrl); + CODE int (*querymenu_scene)(FAR struct v4l2_s *ctx, + FAR struct v4s_querymenu_scene *menu); + CODE int (*g_ext_ctrls_scene)(FAR struct v4l2_s *ctx, + FAR struct v4s_ext_controls_scene *ctrls); + CODE int (*s_ext_ctrls_scene)(FAR struct v4l2_s *ctx, + FAR struct v4s_ext_controls_scene *ctrls); + CODE int (*enum_fmt)(FAR struct v4l2_s *ctx, + FAR struct v4l2_fmtdesc *f); + CODE int (*enum_frminterval)(FAR struct v4l2_s *ctx, + FAR struct v4l2_frmivalenum *f); + CODE int (*enum_frmsize)(FAR struct v4l2_s *ctx, + FAR struct v4l2_frmsizeenum *f); +}; -int video_uninitialize(FAR const char *devpath); +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ /* New API to register video driver. * @@ -92,9 +162,7 @@ int video_uninitialize(FAR const char *devpath); */ int video_register(FAR const char *devpath, - FAR struct imgdata_s *data, - FAR struct imgsensor_s **sensors, - size_t sensor_num); + FAR struct v4l2_s *ctx); /* New API to Unregister video driver. *