[libcamera-devel,06/10] libcamera: camera: Add disconnection notification

Message ID 20190124101651.9993-7-laurent.pinchart@ideasonboard.com
State Accepted
Headers show
Series
  • Hotplug support and object lifetime management
Related show

Commit Message

Laurent Pinchart Jan. 24, 2019, 10:16 a.m. UTC
From: Niklas Söderlund <niklas.soderlund@ragnatech.se>

As camera object have the potential to outlive the hardware they
represent, there is a need to inform the camera that the underlying
device has been disconnected, and in turn to notify applications.

Implement a disconnection notification mechanism that can be used by
pipeline handlers to notify the camera of disconnection. The camera then
block all new API calls and emit the disconnected signal.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 include/libcamera/camera.h |  7 +++++++
 src/libcamera/camera.cpp   | 31 +++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)

Comments

Kieran Bingham Jan. 25, 2019, 9:27 a.m. UTC | #1
Hi Niklas,

On 24/01/2019 10:16, Laurent Pinchart wrote:
> From: Niklas Söderlund <niklas.soderlund@ragnatech.se>
> 
> As camera object have the potential to outlive the hardware they
> represent, there is a need to inform the camera that the underlying
> device has been disconnected, and in turn to notify applications.
> 
> Implement a disconnection notification mechanism that can be used by
> pipeline handlers to notify the camera of disconnection. The camera then
> block all new API calls and emit the disconnected signal.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  include/libcamera/camera.h |  7 +++++++
>  src/libcamera/camera.cpp   | 31 +++++++++++++++++++++++++++++++
>  2 files changed, 38 insertions(+)
> 
> diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h
> index efafb9e28c56..a2ded62de948 100644
> --- a/include/libcamera/camera.h
> +++ b/include/libcamera/camera.h
> @@ -10,6 +10,8 @@
>  #include <memory>
>  #include <string>
>  
> +#include <libcamera/signal.h>
> +
>  namespace libcamera {
>  
>  class PipelineHandler;
> @@ -25,10 +27,15 @@ public:
>  
>  	const std::string &name() const;
>  
> +	Signal<Camera *> disconnected;
> +
>  private:
>  	Camera(PipelineHandler *pipe, const std::string &name);
>  	~Camera();
>  
> +	friend class PipelineHandler;
> +	void disconnect();
> +
>  	std::shared_ptr<PipelineHandler> pipe_;
>  	std::string name_;
>  };
> diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
> index 3a531c7e4d8f..9cec289282e4 100644
> --- a/src/libcamera/camera.cpp
> +++ b/src/libcamera/camera.cpp
> @@ -34,6 +34,8 @@
>  
>  namespace libcamera {
>  
> +LOG_DECLARE_CATEGORY(Camera)
> +
>  /**
>   * \class Camera
>   * \brief Camera device
> @@ -87,6 +89,18 @@ const std::string &Camera::name() const
>  	return name_;
>  }
>  
> +/**
> + * \var Camera::disconnected
> + * \brief Signal emitted when the camera is disconnected from the system
> + *
> + * This signal is emitted when libcamera detects that the cameera has been
> + * removed from the system. For hot-pluggable devices this is usually caused by
> + * physical device disconnection. The media device is passed as a parameter.
> + *
> + * As soon as this signal is emitted the camera instance will refuse all new
> + * application API calls by returning errors immediately.
> + */
> +
>  Camera::Camera(PipelineHandler *pipe, const std::string &name)
>  	: pipe_(pipe->shared_from_this()), name_(name)
>  {
> @@ -96,4 +110,21 @@ Camera::~Camera()
>  {
>  }
>  
> +/**
> + * \brief Notify camera disconnection
> + *
> + * This method is used to notify the camera instance that the underlying
> + * hardware has been unplugged. In response to the disconnection the camera
> + * instance notifies the application by emitting the #disconnected signal, and
> + * ensures that all new calls to the application-facing Camera API return an
> + * error immediately.
> + */
> +void Camera::disconnect()
> +{
> +	LOG(Camera, Debug) << "Disconnecting camera " << name_;
> +
> +	/** \todo Block API calls when they will be implemented. */
> +	disconnected.emit(this);

If only we could have a python function decorator syntax:

@fail_if_disconnected

which would do a pre-check on 'if (!connected) return -ENODEV;' before
the function was called...

I had a quick look at how to emulate function decorators in C++. It's
not pretty - lets just have checks at the beginning of the functions
necessary :)

--
Kieran


> +}
> +
>  } /* namespace libcamera */
>

Patch

diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h
index efafb9e28c56..a2ded62de948 100644
--- a/include/libcamera/camera.h
+++ b/include/libcamera/camera.h
@@ -10,6 +10,8 @@ 
 #include <memory>
 #include <string>
 
+#include <libcamera/signal.h>
+
 namespace libcamera {
 
 class PipelineHandler;
@@ -25,10 +27,15 @@  public:
 
 	const std::string &name() const;
 
+	Signal<Camera *> disconnected;
+
 private:
 	Camera(PipelineHandler *pipe, const std::string &name);
 	~Camera();
 
+	friend class PipelineHandler;
+	void disconnect();
+
 	std::shared_ptr<PipelineHandler> pipe_;
 	std::string name_;
 };
diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
index 3a531c7e4d8f..9cec289282e4 100644
--- a/src/libcamera/camera.cpp
+++ b/src/libcamera/camera.cpp
@@ -34,6 +34,8 @@ 
 
 namespace libcamera {
 
+LOG_DECLARE_CATEGORY(Camera)
+
 /**
  * \class Camera
  * \brief Camera device
@@ -87,6 +89,18 @@  const std::string &Camera::name() const
 	return name_;
 }
 
+/**
+ * \var Camera::disconnected
+ * \brief Signal emitted when the camera is disconnected from the system
+ *
+ * This signal is emitted when libcamera detects that the cameera has been
+ * removed from the system. For hot-pluggable devices this is usually caused by
+ * physical device disconnection. The media device is passed as a parameter.
+ *
+ * As soon as this signal is emitted the camera instance will refuse all new
+ * application API calls by returning errors immediately.
+ */
+
 Camera::Camera(PipelineHandler *pipe, const std::string &name)
 	: pipe_(pipe->shared_from_this()), name_(name)
 {
@@ -96,4 +110,21 @@  Camera::~Camera()
 {
 }
 
+/**
+ * \brief Notify camera disconnection
+ *
+ * This method is used to notify the camera instance that the underlying
+ * hardware has been unplugged. In response to the disconnection the camera
+ * instance notifies the application by emitting the #disconnected signal, and
+ * ensures that all new calls to the application-facing Camera API return an
+ * error immediately.
+ */
+void Camera::disconnect()
+{
+	LOG(Camera, Debug) << "Disconnecting camera " << name_;
+
+	/** \todo Block API calls when they will be implemented. */
+	disconnected.emit(this);
+}
+
 } /* namespace libcamera */