1 /*
2  * dev_tunnelled.h
3  *
4  * Home page of code is: https://www.smartmontools.org
5  *
6  * Copyright (C) 2008-20 Christian Franke
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10 
11 #ifndef DEV_TUNNELLED_H
12 #define DEV_TUNNELLED_H
13 
14 #define DEV_TUNNELLED_H_CVSID "$Id: dev_tunnelled.h 5089 2020-10-06 15:31:47Z chrfranke $"
15 
16 #include "dev_interface.h"
17 
18 /////////////////////////////////////////////////////////////////////////////
19 // tunnelled_device_base
20 
21 /// Common functionality for all tunnelled_device classes.
22 
23 class tunnelled_device_base
24 : virtual public /*implements*/ smart_device
25 {
26 protected:
27   explicit tunnelled_device_base(smart_device * tunnel_dev);
28 
29 public:
30   virtual ~tunnelled_device_base();
31 
32   virtual bool is_open() const;
33 
34   virtual bool open();
35 
36   virtual bool close();
37 
38   virtual bool owns(const smart_device * dev) const;
39 
40   virtual void release(const smart_device * dev);
41 
42 private:
43   smart_device * m_tunnel_base_dev;
44 };
45 
46 
47 /////////////////////////////////////////////////////////////////////////////
48 // tunnelled_device
49 
50 /// Implement a device by tunneling through another device
51 
52 template <class BaseDev, class TunnelDev>
53 class tunnelled_device
54 : public BaseDev,
55   public tunnelled_device_base
56 {
57 public:
58   typedef TunnelDev tunnel_device_type;
59 
60 protected:
tunnelled_device(tunnel_device_type * tunnel_dev)61   explicit tunnelled_device(tunnel_device_type * tunnel_dev)
62     : smart_device(smart_device::never_called),
63       tunnelled_device_base(tunnel_dev),
64       m_tunnel_dev(tunnel_dev)
65     { }
66 
67   // For nvme_device
tunnelled_device(tunnel_device_type * tunnel_dev,unsigned nsid)68   explicit tunnelled_device(tunnel_device_type * tunnel_dev, unsigned nsid)
69     : smart_device(smart_device::never_called),
70       BaseDev(nsid),
71       tunnelled_device_base(tunnel_dev),
72       m_tunnel_dev(tunnel_dev)
73     { }
74 
75 public:
release(const smart_device * dev)76   virtual void release(const smart_device * dev)
77     {
78       if (m_tunnel_dev == dev)
79         m_tunnel_dev = 0;
80       tunnelled_device_base::release(dev);
81     }
82 
get_tunnel_dev()83   tunnel_device_type * get_tunnel_dev()
84     { return m_tunnel_dev; }
85 
get_tunnel_dev()86   const tunnel_device_type * get_tunnel_dev() const
87     { return m_tunnel_dev; }
88 
89 private:
90   tunnel_device_type * m_tunnel_dev;
91 };
92 
93 #endif // DEV_TUNNELLED_H
94