diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig index e05043afbb2..03fc1f642f0 100644 --- a/arch/sim/Kconfig +++ b/arch/sim/Kconfig @@ -265,6 +265,33 @@ endchoice endif +config SIM_VIDEO + bool "Simulated video support" + depends on VIDEO + default y + +if SIM_VIDEO + +choice + prompt "Simulated video device type" + default SIM_VIDEO_V4L2 + +config SIM_VIDEO_V4L2 + bool "V4L2 camera support on sim" + depends on HOST_LINUX + +endchoice + +config HOST_VIDEO_DEV_PATH + string "Host video device path" + default "/dev/video0" + +config SIM_VIDEO_DEV_PATH + string "NuttX video device path" + default "/dev/video" + +endif + menu "Simulated Graphics/Input" config SIM_X11FB @@ -462,10 +489,10 @@ config SIM_UART_NUMBER Under simulation, a NuttX port can be bound to a serial port on the host machine. This way NuttX can access the host's hardware directly. - + There are two possibilities regarding the host's port: it can be either a physical one, or a simulated one. - + In case of a physical port, NuttX will be able to open this port and communicate with any actual hardware that it is connected to. This is useful for testing code that @@ -473,18 +500,18 @@ config SIM_UART_NUMBER In order for this to work, NuttX port name must be set to the same name that the host is using for this port (e.g. /dev/ttyUSB0). - + Alternativelly, a "simulated" host port may be used to. This is useful if you need to also simulate the external hardware, or to have NuttX communicate with any other software in your system. You can create a "simulated" port in your host, by running: - + socat PTY,link=/dev/ttySIM0 PTY,link=/dev/ttyNX0 stty -F /dev/ttySIM0 raw stty -F /dev/ttyNX0 raw - + This will create two new ports on your system. NuttX will use the ttySIM0 port, and another software may open and use the ttyNX0 port. @@ -498,7 +525,7 @@ config SIM_UART_BUFFER_SIZE ---help--- The size of the transmit and receive buffers of the simulated UART ports. - + Note that all ports will have the same buffer size. config SIM_UART0_NAME @@ -508,7 +535,7 @@ config SIM_UART0_NAME ---help--- This is the name of the simulated UART port. The port will be mounted in NuttX under this name. - + A UART port must also exist on the host system with the exact same name specified here. @@ -519,7 +546,7 @@ config SIM_UART1_NAME ---help--- This is the name of the simulated UART port. The port will be mounted in NuttX under this name. - + A UART port must also exist on the host system with the exact same name specified here. @@ -530,7 +557,7 @@ config SIM_UART2_NAME ---help--- This is the name of the simulated UART port. The port will be mounted in NuttX under this name. - + A UART port must also exist on the host system with the exact same name specified here. @@ -541,7 +568,7 @@ config SIM_UART3_NAME ---help--- This is the name of the simulated UART port. The port will be mounted in NuttX under this name. - + A UART port must also exist on the host system with the exact same name specified here. diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile index fe4f705d1bf..38f2242864f 100644 --- a/arch/sim/src/Makefile +++ b/arch/sim/src/Makefile @@ -204,6 +204,12 @@ ifeq ($(CONFIG_SIM_SOUND_ALSA),y) STDLIBS += -lmad endif +ifeq ($(CONFIG_SIM_VIDEO_V4L2),y) + HOSTSRCS += sim_host_v4l2.c + CSRCS += sim_video.c + STDLIBS += -lv4l2 +endif + ifeq ($(CONFIG_SIM_HOSTFS),y) HOSTSRCS += sim_hostfs.c diff --git a/arch/sim/src/sim/posix/sim_host_v4l2.c b/arch/sim/src/sim/posix/sim_host_v4l2.c new file mode 100644 index 00000000000..27facdac6f9 --- /dev/null +++ b/arch/sim/src/sim/posix/sim_host_v4l2.c @@ -0,0 +1,364 @@ +/**************************************************************************** + * arch/sim/src/sim/posix/sim_host_v4l2.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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sim_hostvideo.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAX_REQBUFS 3 + +#define WARN(fmt, ...) \ + syslog(LOG_WARNING, "sim_host_video: " fmt "\n", ##__VA_ARGS__) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct host_video_dev_s +{ + int fd; + void *addrs[MAX_REQBUFS]; + size_t buflen[MAX_REQBUFS]; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int host_video_ioctl(int fd, int request, void *arg) +{ + int r; + + do + { + r = ioctl(fd, request, arg); + } + while (-1 == r && EINTR == errno); + + return r; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +bool host_video_is_available(const char *host_video_dev_path) +{ + return access(host_video_dev_path, F_OK) == 0; +} + +struct host_video_dev_s *host_video_init(const char *host_video_dev_path) +{ + int fd; + struct host_video_dev_s *vdev; + + fd = open(host_video_dev_path, O_RDWR | O_NONBLOCK); + if (fd < 0) + { + perror(host_video_dev_path); + return NULL; + } + + vdev = calloc(1, sizeof(*vdev)); + if (vdev == NULL) + { + perror("host_video_init failed"); + close(fd); + return NULL; + } + + vdev->fd = fd; + return vdev; +} + +int host_video_dq_buf(struct host_video_dev_s *vdev, uint8_t *addr, + uint32_t size) +{ + struct v4l2_buffer buf; + + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + + /* Dequeue a buffer */ + + if (-1 == host_video_ioctl(vdev->fd, VIDIOC_DQBUF, &buf)) + { + switch (errno) + { + case EAGAIN: + + /* No buffer in the outgoing queue */ + + return 0; + + default: + perror("VIDIOC_DQBUF"); + return -errno; + } + } + + if (size > buf.bytesused) + { + size = buf.bytesused; + } + + memcpy(addr, vdev->addrs[buf.index], size); + if (-1 == ioctl(vdev->fd, VIDIOC_QBUF, &buf)) + { + perror("VIDIOC_QBUF"); + return -errno; + } + + return size; +} + +int host_video_uninit(struct host_video_dev_s *vdev) +{ + if (vdev != NULL) + { + close(vdev->fd); + free(vdev); + } + + return 0; +} + +int host_video_start_capture(struct host_video_dev_s *vdev) +{ + struct v4l2_buffer buf; + struct v4l2_requestbuffers reqbuf; + enum v4l2_buf_type type; + int i; + + /* VIDIOC_REQBUFS initiate user pointer I/O */ + + memset(&reqbuf, 0, sizeof(reqbuf)); + reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + reqbuf.memory = V4L2_MEMORY_MMAP; + reqbuf.count = MAX_REQBUFS; + + if (-1 == host_video_ioctl(vdev->fd, VIDIOC_REQBUFS, &reqbuf)) + { + perror("VIDIOC_REQBUFS"); + return -errno; + } + + if (reqbuf.count < 2) + { + errno = ENOMEM; + perror("Not enough buffers"); + return -ENOMEM; + } + + for (i = 0; i < reqbuf.count; i++) + { + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + if (-1 == host_video_ioctl(vdev->fd, VIDIOC_QUERYBUF, &buf)) + { + perror("VIDIOC_QUERYBUF"); + goto err_out; + } + + vdev->addrs[i] = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, + MAP_SHARED, vdev->fd, buf.m.offset); + if (vdev->addrs[i] == MAP_FAILED) + { + perror("Mmap failed"); + goto err_out; + } + + vdev->buflen[i] = buf.length; + if (-1 == host_video_ioctl(vdev->fd, VIDIOC_QBUF, &buf)) + { + perror("VIDIOC_QBUF"); + goto err_out; + } + } + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == host_video_ioctl(vdev->fd, VIDIOC_STREAMON, &type)) + { + perror("VIDIOC_STREAMON"); + goto err_out; + } + + return 0; + +err_out: + while (i--) + { + munmap(vdev->addrs[i], vdev->buflen[i]); + vdev->addrs[i] = NULL; + vdev->buflen[i] = 0; + } + + return -errno; +} + +int host_video_stop_capture(struct host_video_dev_s *vdev) +{ + enum v4l2_buf_type type; + int i; + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == host_video_ioctl(vdev->fd, VIDIOC_STREAMOFF, &type)) + { + perror("VIDIOC_STREAMOFF"); + return -errno; + } + + for (i = 0; i < MAX_REQBUFS; i++) + { + if (vdev->buflen[i] == 0) + { + break; + } + + munmap(vdev->addrs[i], vdev->buflen[i]); + vdev->addrs[i] = NULL; + vdev->buflen[i] = 0; + } + + return 0; +} + +int host_video_set_fmt(struct host_video_dev_s *vdev, + uint16_t width, uint16_t height, uint32_t fmt, + uint32_t denom, uint32_t numer) +{ + struct v4l2_format v4l2_fmt; + struct v4l2_streamparm streamparm; + + memset(&v4l2_fmt, 0, sizeof(v4l2_fmt)); + v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2_fmt.fmt.pix.width = width; + v4l2_fmt.fmt.pix.height = height; + v4l2_fmt.fmt.pix.pixelformat = fmt; + v4l2_fmt.fmt.pix.field = V4L2_FIELD_NONE; + + if (-1 == host_video_ioctl(vdev->fd, VIDIOC_S_FMT, &v4l2_fmt)) + { + perror("VIDIOC_S_FMT"); + return -errno; + } + + memset(&streamparm, 0, sizeof(streamparm)); + streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == host_video_ioctl(vdev->fd, VIDIOC_G_PARM, &streamparm)) + { + perror("VIDIOC_G_PARM"); + return -errno; + } + + streamparm.parm.capture.capturemode |= V4L2_CAP_TIMEPERFRAME; + streamparm.parm.capture.timeperframe.numerator = numer; + streamparm.parm.capture.timeperframe.denominator = denom; + if (-1 == host_video_ioctl(vdev->fd, VIDIOC_S_PARM, &streamparm)) + { + perror("VIDIOC_S_PARM"); + return -errno; + } + + return 0; +} + +int host_video_try_fmt(struct host_video_dev_s *vdev, + uint16_t width, uint16_t height, uint32_t fmt, + uint32_t denom, uint32_t numer) +{ + struct v4l2_format v4l2_fmt; + struct v4l2_frmivalenum v4l2_frmival; + + memset(&v4l2_fmt, 0, sizeof(v4l2_fmt)); + v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2_fmt.fmt.pix.width = width; + v4l2_fmt.fmt.pix.height = height; + v4l2_fmt.fmt.pix.pixelformat = fmt; + v4l2_fmt.fmt.pix.field = V4L2_FIELD_NONE; + + if (-1 == host_video_ioctl(vdev->fd, VIDIOC_TRY_FMT, &v4l2_fmt)) + { + perror("VIDIOC_TRY_FMT"); + return -errno; + } + + if (v4l2_fmt.fmt.pix.pixelformat != fmt) + { + WARN("Pixel format not supported"); + return -EINVAL; + } + + /* Need not check frame interval for STILL type */ + + if (!denom) + { + memset(&v4l2_frmival, 0, sizeof(v4l2_frmival)); + v4l2_frmival.width = width; + v4l2_frmival.height = height; + v4l2_frmival.pixel_format = fmt; + while (host_video_ioctl(vdev->fd, VIDIOC_ENUM_FRAMEINTERVALS, + &v4l2_frmival) == 0) + { + if (v4l2_frmival.type == V4L2_FRMSIZE_TYPE_DISCRETE && + v4l2_frmival.discrete.denominator == denom && + v4l2_frmival.discrete.numerator == numer) + { + return 0; + } + + v4l2_frmival.index++; + } + + WARN("Invalid frame interval, fallback to default"); + } + + return 0; +} diff --git a/arch/sim/src/sim/sim_hostvideo.h b/arch/sim/src/sim/sim_hostvideo.h new file mode 100644 index 00000000000..84414319960 --- /dev/null +++ b/arch/sim/src/sim/sim_hostvideo.h @@ -0,0 +1,55 @@ +/**************************************************************************** + * arch/sim/src/sim/sim_hostvideo.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 __ARCH_SIM_SRC_SIM_SIM_HOSTVIDEO_H +#define __ARCH_SIM_SRC_SIM_SIM_HOSTVIDEO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +struct host_video_dev_s; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +bool host_video_is_available(const char *host_video_dev_path); +struct host_video_dev_s *host_video_init(const char *host_video_dev_path); +int host_video_uninit(struct host_video_dev_s *vdev); +int host_video_start_capture(struct host_video_dev_s *vdev); +int host_video_stop_capture(struct host_video_dev_s *vdev); +int host_video_dq_buf(struct host_video_dev_s *vdev, uint8_t *addr, + uint32_t size); +int host_video_set_fmt(struct host_video_dev_s *vdev, + uint16_t width, uint16_t height, uint32_t fmt, + uint32_t denom, uint32_t numer); +int host_video_try_fmt(struct host_video_dev_s *vdev, + uint16_t width, uint16_t height, uint32_t fmt, + uint32_t denom, uint32_t numer); + +#endif /* __ARCH_SIM_SRC_SIM_SIM_HOSTVIDEO_H */ diff --git a/arch/sim/src/sim/sim_initialize.c b/arch/sim/src/sim/sim_initialize.c index fefe0a521f5..48af8bde778 100644 --- a/arch/sim/src/sim/sim_initialize.c +++ b/arch/sim/src/sim/sim_initialize.c @@ -195,6 +195,10 @@ static int sim_loop_task(int argc, char **argv) sim_audio_loop(); #endif +#ifdef CONFIG_SIM_VIDEO + sim_video_loop(); +#endif + #ifdef CONFIG_MOTOR_FOC_DUMMY /* Update simulated FOC device */ diff --git a/arch/sim/src/sim/sim_internal.h b/arch/sim/src/sim/sim_internal.h index e56971c8e9b..d29718fdd46 100644 --- a/arch/sim/src/sim/sim_internal.h +++ b/arch/sim/src/sim/sim_internal.h @@ -357,6 +357,13 @@ struct spi_dev_s *sim_spi_initialize(const char *filename); int sim_spi_uninitialize(struct spi_dev_s *dev); #endif +/* up_video.c ***************************************************************/ + +#ifdef CONFIG_SIM_VIDEO +int sim_video_initialize(void); +void sim_video_loop(void); +#endif + /* Debug ********************************************************************/ #ifdef CONFIG_STACK_COLORATION diff --git a/arch/sim/src/sim/sim_video.c b/arch/sim/src/sim/sim_video.c new file mode 100644 index 00000000000..7ec0aca5ccf --- /dev/null +++ b/arch/sim/src/sim/sim_video.c @@ -0,0 +1,314 @@ +/**************************************************************************** + * arch/sim/src/sim/sim_video.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 +#include + +#include "sim_hostvideo.h" +#include "sim_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +typedef struct +{ + imgdata_capture_t capture_cb; + uint32_t buf_size; + uint8_t *next_buf; + struct host_video_dev_s *vdev; +} sim_video_priv_t; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Video image sensor operations */ + +static bool sim_video_is_available(void); +static int sim_video_init(void); +static int sim_video_uninit(void); +static const char *sim_video_get_driver_name(void); +static int sim_video_validate_frame_setting(imgsensor_stream_type_t type, + uint8_t nr_datafmt, + imgsensor_format_t *datafmts, + imgsensor_interval_t *interval); +static int sim_video_start_capture(imgsensor_stream_type_t type, + uint8_t nr_datafmt, + imgsensor_format_t *datafmts, + imgsensor_interval_t *interval); +static int sim_video_stop_capture(imgsensor_stream_type_t type); + +/* Video image data operations */ + +static int sim_video_data_init(void); +static int sim_video_data_uninit(void); +static int sim_video_data_validate_frame_setting(uint8_t nr_datafmt, + imgdata_format_t *datafmt, + imgdata_interval_t *interv); +static int sim_video_data_start_capture(uint8_t nr_datafmt, + imgdata_format_t *datafmt, + imgdata_interval_t *interval, + imgdata_capture_t callback); +static int sim_video_data_stop_capture(void); +static int sim_video_data_validate_buf(uint8_t *addr, uint32_t size); +static int sim_video_data_set_buf(uint8_t *addr, uint32_t size); + +static uint32_t imgdata_fmt_to_v4l2(uint32_t pixelformat); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct imgsensor_ops_s g_sim_video_ops = +{ + .is_available = sim_video_is_available, + .init = sim_video_init, + .uninit = sim_video_uninit, + .get_driver_name = sim_video_get_driver_name, + .validate_frame_setting = sim_video_validate_frame_setting, + .start_capture = sim_video_start_capture, + .stop_capture = sim_video_stop_capture, +}; + +static const struct imgdata_ops_s g_sim_video_data_ops = +{ + .init = sim_video_data_init, + .uninit = sim_video_data_uninit, + .validate_buf = sim_video_data_validate_buf, + .set_buf = sim_video_data_set_buf, + .validate_frame_setting = sim_video_data_validate_frame_setting, + .start_capture = sim_video_data_start_capture, + .stop_capture = sim_video_data_stop_capture, +}; + +static sim_video_priv_t g_sim_video_priv; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Sensor op functions are mostly dummy */ + +static bool sim_video_is_available(void) +{ + return host_video_is_available(CONFIG_HOST_VIDEO_DEV_PATH); +} + +static int sim_video_init(void) +{ + return 0; +} + +static int sim_video_uninit(void) +{ + return 0; +} + +static const char *sim_video_get_driver_name(void) +{ + return "V4L2 NuttX Sim Driver"; +} + +static int sim_video_validate_frame_setting(imgsensor_stream_type_t type, + uint8_t nr_fmt, + imgsensor_format_t *fmt, + imgsensor_interval_t *interval) +{ + return 0; +} + +static int sim_video_start_capture(imgsensor_stream_type_t type, + uint8_t nr_fmt, + imgsensor_format_t *fmt, + imgsensor_interval_t *interval) +{ + return 0; +} + +static int sim_video_stop_capture(imgsensor_stream_type_t type) +{ + return 0; +} + +/* Data op functions do all the real work */ + +static int sim_video_data_init(void) +{ + memset(&g_sim_video_priv, 0, sizeof(g_sim_video_priv)); + g_sim_video_priv.vdev = host_video_init(CONFIG_HOST_VIDEO_DEV_PATH); + if (g_sim_video_priv.vdev == NULL) + { + return -ENODEV; + } + + return 0; +} + +static int sim_video_data_uninit(void) +{ + return host_video_uninit(g_sim_video_priv.vdev); +} + +static int sim_video_data_validate_buf(uint8_t *addr, uint32_t size) +{ + if (!addr || ((uintptr_t)(addr) & 0x1f)) + { + return -EINVAL; + } + + return 0; +} + +static int sim_video_data_set_buf(uint8_t *addr, uint32_t size) +{ + g_sim_video_priv.next_buf = addr; + g_sim_video_priv.buf_size = size; + return 0; +} + +static int sim_video_data_validate_frame_setting(uint8_t nr_datafmt, + imgdata_format_t *datafmt, + imgdata_interval_t *interv) +{ + uint32_t v4l2_fmt; + + if (nr_datafmt > 1) + { + return -ENOTSUP; + } + + v4l2_fmt = imgdata_fmt_to_v4l2(datafmt->pixelformat); + return host_video_try_fmt(g_sim_video_priv.vdev, datafmt->width, + datafmt->height, v4l2_fmt, interv->denominator, + interv->numerator); +} + +static int sim_video_data_start_capture(uint8_t nr_datafmt, + imgdata_format_t *datafmt, + imgdata_interval_t *interval, + imgdata_capture_t callback) +{ + int ret; + + ret = host_video_set_fmt(g_sim_video_priv.vdev, + datafmt[IMGDATA_FMT_MAIN].width, + datafmt[IMGDATA_FMT_MAIN].height, + imgdata_fmt_to_v4l2( + datafmt[IMGDATA_FMT_MAIN].pixelformat), + interval->denominator, interval->numerator); + if (ret < 0) + { + return ret; + } + + g_sim_video_priv.capture_cb = callback; + return host_video_start_capture(g_sim_video_priv.vdev); +} + +static int sim_video_data_stop_capture(void) +{ + g_sim_video_priv.next_buf = NULL; + return host_video_stop_capture(g_sim_video_priv.vdev); +} + +/* Helper functions */ + +static uint32_t imgdata_fmt_to_v4l2(uint32_t pixelformat) +{ + uint32_t fourcc; + switch (pixelformat) + { + case IMGDATA_PIX_FMT_YUV420P: + fourcc = V4L2_PIX_FMT_YUV420; + break; + + case IMGDATA_PIX_FMT_YUYV: + fourcc = V4L2_PIX_FMT_YUYV; + break; + + case IMGDATA_PIX_FMT_JPEG_WITH_SUBIMG: + fourcc = V4L2_PIX_FMT_JPEG; + break; + + case IMGDATA_PIX_FMT_JPEG: + fourcc = V4L2_PIX_FMT_JPEG; + break; + + case IMGDATA_PIX_FMT_RGB565: + fourcc = V4L2_PIX_FMT_RGB565; + break; + + case IMGDATA_PIX_FMT_UYVY: + fourcc = V4L2_PIX_FMT_UYVY; + break; + + default: + + /* Unsupported format */ + + fourcc = 0; + } + + return fourcc; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int sim_video_initialize(void) +{ + imgsensor_register(&g_sim_video_ops); + imgdata_register(&g_sim_video_data_ops); + return 0; +} + +int sim_video_uninitialize(void) +{ + return 0; +} + +void sim_video_loop(void) +{ + int ret; + + if (g_sim_video_priv.next_buf) + { + ret = host_video_dq_buf(g_sim_video_priv.vdev, + g_sim_video_priv.next_buf, + g_sim_video_priv.buf_size); + if (ret > 0) + { + g_sim_video_priv.capture_cb(0, ret); + } + } +} diff --git a/boards/sim/sim/sim/src/sim_bringup.c b/boards/sim/sim/sim/src/sim_bringup.c index 4234e1bad58..8d976546cb4 100644 --- a/boards/sim/sim/sim/src/sim_bringup.c +++ b/boards/sim/sim/sim/src/sim_bringup.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -291,6 +292,18 @@ int sim_bringup(void) } #endif +#ifdef CONFIG_SIM_VIDEO + /* Initialize and register the simulated video driver */ + + ret = video_initialize(CONFIG_SIM_VIDEO_DEV_PATH); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: video_initialize() failed: %d\n", ret); + } + + sim_video_initialize(); +#endif + #ifdef CONFIG_LCD ret = board_lcd_initialize();