You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by pk...@apache.org on 2022/05/30 17:38:56 UTC

[incubator-nuttx] 03/11: drivers/video: Enable to select connected image sensor driver at runtime

This is an automated email from the ASF dual-hosted git repository.

pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit b45489753aaf914669b5f130915ee9d739e82e7f
Author: SPRESENSE <41...@users.noreply.github.com>
AuthorDate: Mon Nov 29 09:31:43 2021 +0900

    drivers/video: Enable to select connected image sensor driver at runtime
    
    Enable to select connected image sensor driver at runtime by adding is_available()
    to image sensor I/F.
---
 drivers/video/isx012.c          | 52 ++++++++++++++++++++++++++++++++++++++++-
 drivers/video/video.c           | 52 ++++++++++++++++++++++++++++++++++++-----
 include/nuttx/video/imgsensor.h | 43 +++++++++++++++++-----------------
 3 files changed, 119 insertions(+), 28 deletions(-)

diff --git a/drivers/video/isx012.c b/drivers/video/isx012.c
index ea4658e8f1..83f06d77e5 100644
--- a/drivers/video/isx012.c
+++ b/drivers/video/isx012.c
@@ -140,6 +140,9 @@
                                               (((val - min) % step) == 0) ? \
                                               OK : -EINVAL))
 
+#define ISX012_CHIPID_L (0x0000c460)
+#define ISX012_CHIPID_H (0x00005516)
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -215,6 +218,7 @@ static bool is_movie_needed(uint8_t fmt, uint8_t fps);
 
 /* image sensor device operations interface */
 
+static bool isx012_is_available(void);
 static int isx012_init(void);
 static int isx012_uninit(void);
 static const char *isx012_get_driver_name(void);
@@ -615,6 +619,7 @@ static uint8_t g_isx012_iso_regval[] =
 
 static struct imgsensor_ops_s g_isx012_ops =
 {
+  isx012_is_available,                  /* is HW available */
   isx012_init,                          /* init */
   isx012_uninit,                        /* uninit */
   isx012_get_driver_name,               /* get driver name */
@@ -1236,6 +1241,45 @@ int init_isx012(FAR struct isx012_dev_s *priv)
   return ret;
 }
 
+static void get_chipid(uint32_t *l, uint32_t *h)
+{
+  uint16_t l1;
+  uint16_t l2;
+  uint16_t h1;
+  uint16_t h2;
+
+  ASSERT(l && h);
+
+  l1 = isx012_getreg(&g_isx012_private, OTP_CHIPID_L, 2);
+  l2 = isx012_getreg(&g_isx012_private, OTP_CHIPID_L + 2, 2);
+
+  h1 = isx012_getreg(&g_isx012_private, OTP_CHIPID_H, 2);
+  h2 = isx012_getreg(&g_isx012_private, OTP_CHIPID_H + 2, 2);
+
+  *l = (l2 << 16) | l1;
+  *h = (h2 << 16) | h1;
+}
+
+static bool isx012_is_available(void)
+{
+  bool ret = false;
+  uint32_t l;
+  uint32_t h;
+
+  isx012_init();
+
+  get_chipid(&l, &h);
+
+  if ((l == ISX012_CHIPID_L) && (h == ISX012_CHIPID_H))
+    {
+      ret = true;
+    }
+
+  isx012_uninit();
+
+  return ret;
+}
+
 static int isx012_init(void)
 {
   FAR struct isx012_dev_s *priv = &g_isx012_private;
@@ -2885,11 +2929,17 @@ static int isx012_set_shd(FAR isx012_dev_t *priv)
 
 int isx012_initialize(void)
 {
+  int ret;
   FAR struct isx012_dev_s *priv = &g_isx012_private;
 
   /* Regiser image sensor operations variable */
 
-  imgsensor_register(&g_isx012_ops);
+  ret = imgsensor_register(&g_isx012_ops);
+  if (ret != OK)
+    {
+      verr("Failed to register ops to video driver.\n");
+      return ret;
+    }
 
   /* Initialize other information */
 
diff --git a/drivers/video/video.c b/drivers/video/video.c
index 79b4c6f3ba..c8e4980cd1 100644
--- a/drivers/video/video.c
+++ b/drivers/video/video.c
@@ -398,6 +398,8 @@ static video_parameter_name_t g_video_parameter_name[] =
 };
 
 static FAR void *video_handler;
+static FAR const struct imgsensor_ops_s **g_video_registered_sensor;
+static int g_video_registered_sensor_num;
 static FAR const struct imgsensor_ops_s *g_video_sensor_ops;
 static FAR const struct imgdata_ops_s *g_video_data_ops;
 
@@ -930,6 +932,24 @@ static bool is_sem_waited(FAR sem_t *sem)
     }
 }
 
+static FAR const struct imgsensor_ops_s *get_connected_imgsensor(void)
+{
+  int i;
+  FAR const struct imgsensor_ops_s *ops = NULL;
+
+  for (i = 0; i < g_video_registered_sensor_num; i++)
+    {
+      if (g_video_registered_sensor[i] &&
+          g_video_registered_sensor[i]->is_available())
+        {
+          ops = g_video_registered_sensor[i];
+          break;
+        }
+    }
+
+  return ops;
+}
+
 static int video_open(FAR struct file *filep)
 {
   FAR struct inode *inode = filep->f_inode;
@@ -941,15 +961,23 @@ static int video_open(FAR struct file *filep)
     {
       /* Only in first execution, open device */
 
-      ret = g_video_sensor_ops->init();
-      if (ret == OK)
+      g_video_sensor_ops = get_connected_imgsensor();
+      if (g_video_sensor_ops)
         {
-          ret = g_video_data_ops->init();
+          ret = g_video_sensor_ops->init();
           if (ret == OK)
             {
-              initialize_resources(priv);
+              ret = g_video_data_ops->init();
+              if (ret == OK)
+                {
+                  initialize_resources(priv);
+                }
             }
         }
+      else
+        {
+          ret = -ENODEV;
+        }
     }
 
   /* In second or later execution, ret is initial value(=OK) */
@@ -3018,9 +3046,21 @@ int video_uninitialize(void)
   return OK;
 }
 
-void imgsensor_register(FAR const struct imgsensor_ops_s *ops)
+int imgsensor_register(FAR const struct imgsensor_ops_s *ops)
 {
-  g_video_sensor_ops = ops;
+  int ret = -ENOMEM;
+  FAR const struct imgsensor_ops_s **new_addr;
+
+  new_addr = realloc(g_video_registered_sensor,
+                     sizeof(ops) * (g_video_registered_sensor_num + 1));
+  if (new_addr)
+    {
+      new_addr[g_video_registered_sensor_num++] = ops;
+      g_video_registered_sensor = new_addr;
+      ret = OK;
+    }
+
+  return ret;
 }
 
 void imgdata_register(FAR const struct imgdata_ops_s *ops)
diff --git a/include/nuttx/video/imgsensor.h b/include/nuttx/video/imgsensor.h
index 0254250cf7..8d1f60109b 100644
--- a/include/nuttx/video/imgsensor.h
+++ b/include/nuttx/video/imgsensor.h
@@ -303,27 +303,28 @@ typedef union imgsensor_value_u
 
 struct imgsensor_ops_s
 {
-  CODE int (*init)(void);
-  CODE int (*uninit)(void);
+  CODE bool (*is_available)(void);
+  CODE int  (*init)(void);
+  CODE int  (*uninit)(void);
   CODE const char * (*get_driver_name)(void);
-  CODE int (*validate_frame_setting)(imgsensor_stream_type_t type,
-                                     uint8_t nr_datafmts,
-                                     FAR imgsensor_format_t *datafmts,
-                                     FAR imgsensor_interval_t *interval);
-  CODE int (*start_capture)(imgsensor_stream_type_t type,
-                            uint8_t nr_datafmts,
-                            FAR imgsensor_format_t *datafmts,
-                            FAR imgsensor_interval_t *interval);
-  CODE int (*stop_capture)(imgsensor_stream_type_t type);
-
-  CODE int (*get_supported_value)(uint32_t id,
-                                  FAR imgsensor_supported_value_t *value);
-  CODE int (*get_value)(uint32_t id,
-                        uint32_t size,
-                        FAR imgsensor_value_t *value);
-  CODE int (*set_value)(uint32_t id,
-                        uint32_t size,
-                        imgsensor_value_t value);
+  CODE int  (*validate_frame_setting)(imgsensor_stream_type_t type,
+                                      uint8_t nr_datafmts,
+                                      FAR imgsensor_format_t *datafmts,
+                                      FAR imgsensor_interval_t *interval);
+  CODE int  (*start_capture)(imgsensor_stream_type_t type,
+                             uint8_t nr_datafmts,
+                             FAR imgsensor_format_t *datafmts,
+                             FAR imgsensor_interval_t *interval);
+  CODE int  (*stop_capture)(imgsensor_stream_type_t type);
+
+  CODE int  (*get_supported_value)(uint32_t id,
+                                   FAR imgsensor_supported_value_t *value);
+  CODE int  (*get_value)(uint32_t id,
+                         uint32_t size,
+                         FAR imgsensor_value_t *value);
+  CODE int  (*set_value)(uint32_t id,
+                         uint32_t size,
+                         imgsensor_value_t value);
 };
 
 #ifdef __cplusplus
@@ -340,7 +341,7 @@ extern "C"
 
 /* Register image sensor operations. */
 
-void imgsensor_register(FAR const struct imgsensor_ops_s *ops);
+int imgsensor_register(FAR const struct imgsensor_ops_s *ops);
 
 #undef EXTERN
 #ifdef __cplusplus