smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
dev_interface.h
Go to the documentation of this file.
00001 /*
00002  * dev_interface.h
00003  *
00004  * Home page of code is: http://smartmontools.sourceforge.net
00005  *
00006  * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012  *
00013  * You should have received a copy of the GNU General Public License
00014  * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
00015  *
00016  */
00017 
00018 #ifndef DEV_INTERFACE_H
00019 #define DEV_INTERFACE_H
00020 
00021 #define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 3663 2012-10-24 20:35:55Z chrfranke $\n"
00022 
00023 #include "utility.h"
00024 
00025 #include <stdexcept>
00026 #include <string>
00027 #include <vector>
00028 
00029 /////////////////////////////////////////////////////////////////////////////
00030 // Common functionality for all device types
00031 
00032 // Forward declarations
00033 class smart_interface;
00034 class ata_device;
00035 class scsi_device;
00036 
00037 /// Base class for all devices
00038 class smart_device
00039 {
00040 // Types
00041 public:
00042   /// Device info strings
00043   struct device_info {
00044     device_info()
00045       { }
00046     device_info(const char * d_name, const char * d_type, const char * r_type)
00047       : dev_name(d_name), info_name(d_name),
00048         dev_type(d_type), req_type(r_type)
00049       { }
00050 
00051     std::string dev_name;  ///< Device (path)name
00052     std::string info_name; ///< Informal name
00053     std::string dev_type;  ///< Actual device type
00054     std::string req_type;  ///< Device type requested by user, empty if none
00055   };
00056 
00057   /// Error (number,message) pair
00058   struct error_info {
00059     explicit error_info(int n = 0)
00060       : no(n) { }
00061     error_info(int n, const char * m)
00062       : no(n), msg(m) { }
00063     void clear()
00064       { no = 0; msg.erase(); }
00065 
00066     int no;          ///< Error number
00067     std::string msg; ///< Error message
00068   };
00069 
00070 // Construction
00071 protected:
00072   /// Constructor to init interface and device info.
00073   /// Must be called in implementation classes.
00074   smart_device(smart_interface * intf, const char * dev_name,
00075     const char * dev_type, const char * req_type);
00076 
00077   /// Dummy enum for dummy constructor.
00078   enum do_not_use_in_implementation_classes { never_called };
00079   /// Dummy constructor for abstract classes.
00080   /// Must never be called in implementation classes.
00081   smart_device(do_not_use_in_implementation_classes);
00082 
00083 public:
00084   virtual ~smart_device() throw();
00085 
00086 // Attributes
00087 public:
00088   ///////////////////////////////////////////////
00089   // Dynamic downcasts to actual device flavor
00090 
00091   /// Return true if ATA device
00092   bool is_ata() const
00093     { return !!m_ata_ptr; }
00094   /// Return true if SCSI device
00095   bool is_scsi() const
00096     { return !!m_scsi_ptr; }
00097 
00098   /// Downcast to ATA device.
00099   ata_device * to_ata()
00100     { return m_ata_ptr; }
00101   /// Downcast to ATA device (const).
00102   const ata_device * to_ata() const
00103     { return m_ata_ptr; }
00104   /// Downcast to SCSI device.
00105   scsi_device * to_scsi()
00106     { return m_scsi_ptr; }
00107   /// Downcast to SCSI device (const).
00108   const scsi_device * to_scsi() const
00109     { return m_scsi_ptr; }
00110 
00111   ///////////////////////////////////////////////
00112   // Device information
00113 
00114   /// Get device info struct.
00115   const device_info & get_info() const
00116     { return m_info; }
00117 
00118   /// Get device (path)name.
00119   const char * get_dev_name() const
00120     { return m_info.dev_name.c_str(); }
00121   /// Get informal name.
00122   const char * get_info_name() const
00123     { return m_info.info_name.c_str(); }
00124   /// Get device type.
00125   const char * get_dev_type() const
00126     { return m_info.dev_type.c_str(); }
00127   /// Get type requested by user, empty if none.
00128   const char * get_req_type() const
00129     { return m_info.req_type.c_str(); }
00130 
00131 protected:
00132   /// R/W access to device info struct.
00133   device_info & set_info()
00134     { return m_info; }
00135 
00136 public:
00137   ///////////////////////////////////////////////
00138   // Last error information
00139 
00140   /// Get last error info struct.
00141   const error_info & get_err() const
00142     { return m_err; }
00143   /// Get last error number.
00144   int get_errno() const
00145     { return m_err.no; }
00146   /// Get last error message.
00147   const char * get_errmsg() const
00148     { return m_err.msg.c_str(); }
00149 
00150   /// Return true if last error indicates an unsupported system call.
00151   /// Default implementation returns true on ENOSYS and ENOTSUP.
00152   virtual bool is_syscall_unsup() const;
00153 
00154   /// Set last error number and message.
00155   /// Printf()-like formatting is supported.
00156   /// Returns false always to allow use as a return expression.
00157   bool set_err(int no, const char * msg, ...)
00158     __attribute_format_printf(3, 4);
00159 
00160   /// Set last error info struct.
00161   bool set_err(const error_info & err)
00162     { m_err = err; return false; }
00163 
00164   /// Clear last error info.
00165   void clear_err()
00166     { m_err.clear(); }
00167 
00168   /// Set last error number and default message.
00169   /// Message is retrieved from interface's get_msg_for_errno(no).
00170   bool set_err(int no);
00171 
00172 // Operations
00173 public:
00174   ///////////////////////////////////////////////
00175   // Device open/close
00176   // Must be implemented in derived class
00177 
00178   /// Return true if device is open.
00179   virtual bool is_open() const = 0;
00180 
00181   /// Open device, return false on error.
00182   virtual bool open() = 0;
00183 
00184   /// Close device, return false on error.
00185   virtual bool close() = 0;
00186 
00187   /// Open device with autodetection support.
00188   /// May return another device for further access.
00189   /// In this case, the original pointer is no longer valid.
00190   /// Default implementation calls 'open()' and returns 'this'.
00191   virtual smart_device * autodetect_open();
00192 
00193   ///////////////////////////////////////////////
00194   // Support for tunnelled devices
00195 
00196   /// Return true if other device is owned by this device.
00197   /// Default implementation returns false.
00198   virtual bool owns(const smart_device * dev) const;
00199 
00200   /// Release ownership of other device.
00201   /// Default implementation does nothing.
00202   virtual void release(const smart_device * dev);
00203 
00204 protected:
00205   /// Get interface which produced this object.
00206   smart_interface * smi()
00207     { return m_intf; }
00208   /// Get interface which produced this object (const).
00209   const smart_interface * smi() const
00210     { return m_intf; }
00211 
00212 // Implementation
00213 private:
00214   smart_interface * m_intf;
00215   device_info m_info;
00216   error_info m_err;
00217 
00218   // Pointers for to_ata(), to_scsi(),
00219   // set by ATA/SCSI interface classes.
00220   friend class ata_device;
00221   ata_device * m_ata_ptr;
00222   friend class scsi_device;
00223   scsi_device * m_scsi_ptr;
00224 
00225   // Prevent copy/assigment
00226   smart_device(const smart_device &);
00227   void operator=(const smart_device &);
00228 };
00229 
00230 
00231 /////////////////////////////////////////////////////////////////////////////
00232 // ATA specific interface
00233 
00234 /// ATA register value and info whether it has ever been set
00235 // (Automatically set by first assignment)
00236 class ata_register
00237 {
00238 public:
00239   ata_register()
00240     : m_val(0x00), m_is_set(false) { }
00241 
00242   ata_register & operator=(unsigned char x)
00243     { m_val = x; m_is_set = true; return * this; }
00244 
00245   unsigned char val() const
00246     { return m_val; }
00247   operator unsigned char() const
00248     { return m_val; }
00249 
00250   bool is_set() const
00251     { return m_is_set; }
00252 
00253 private:
00254   unsigned char m_val; ///< Register value
00255   bool m_is_set; ///< true if set
00256 };
00257 
00258 /// ATA Input registers (for 28-bit commands)
00259 struct ata_in_regs
00260 {
00261   // ATA-6/7 register names  // ATA-3/4/5        // ATA-8
00262   ata_register features;     // features         // features
00263   ata_register sector_count; // sector count     // count
00264   ata_register lba_low;      // sector number    // ]
00265   ata_register lba_mid;      // cylinder low     // ] lba
00266   ata_register lba_high;     // cylinder high    // ]
00267   ata_register device;       // device/head      // device
00268   ata_register command;      // command          // command
00269 
00270   /// Return true if any register is set
00271   bool is_set() const
00272     { return (features.is_set() || sector_count.is_set()
00273       || lba_low.is_set() || lba_mid.is_set() || lba_high.is_set()
00274       || device.is_set() || command.is_set());                    }
00275 };
00276 
00277 /// ATA Output registers (for 28-bit commands)
00278 struct ata_out_regs
00279 {
00280   ata_register error;
00281   ata_register sector_count;
00282   ata_register lba_low;
00283   ata_register lba_mid;
00284   ata_register lba_high;
00285   ata_register device;
00286   ata_register status;
00287 
00288   /// Return true if any register is set
00289   bool is_set() const
00290     { return (error.is_set() || sector_count.is_set()
00291       || lba_low.is_set() || lba_mid.is_set() || lba_high.is_set()
00292       || device.is_set() || status.is_set());                      }
00293 };
00294 
00295 
00296 /// 16-bit alias to a 8-bit ATA register pair.
00297 class ata_reg_alias_16
00298 {
00299 public:
00300   ata_reg_alias_16(ata_register & lo, ata_register & hi)
00301     : m_lo(lo), m_hi(hi) { }
00302 
00303   ata_reg_alias_16 & operator=(unsigned short x)
00304     { m_lo = (unsigned char) x;
00305       m_hi = (unsigned char)(x >> 8);
00306       return * this;                   }
00307 
00308   unsigned short val() const
00309     { return m_lo | (m_hi << 8); }
00310   operator unsigned short() const
00311     { return m_lo | (m_hi << 8); }
00312 
00313 private:
00314   ata_register & m_lo, & m_hi;
00315 
00316   // References must not be copied.
00317   ata_reg_alias_16(const ata_reg_alias_16 &);
00318   void operator=(const ata_reg_alias_16 &);
00319 };
00320 
00321 
00322 /// 48-bit alias to six 8-bit ATA registers (for LBA).
00323 class ata_reg_alias_48
00324 {
00325 public:
00326   ata_reg_alias_48(ata_register & ll, ata_register & lm, ata_register & lh,
00327                    ata_register & hl, ata_register & hm, ata_register & hh)
00328     : m_ll(ll), m_lm(lm), m_lh(lh),
00329       m_hl(hl), m_hm(hm), m_hh(hh)
00330     { }
00331 
00332   ata_reg_alias_48 & operator=(uint64_t x)
00333     {
00334       m_ll = (unsigned char) x;
00335       m_lm = (unsigned char)(x >>  8);
00336       m_lh = (unsigned char)(x >> 16);
00337       m_hl = (unsigned char)(x >> 24);
00338       m_hm = (unsigned char)(x >> 32);
00339       m_hh = (unsigned char)(x >> 40);
00340       return * this;
00341     }
00342 
00343   uint64_t val() const
00344     {
00345       return (   (unsigned)m_ll
00346               | ((unsigned)m_lm <<  8)
00347               | ((unsigned)m_lh << 16)
00348               | ((unsigned)m_hl << 24)
00349               | ((uint64_t)m_hm << 32)
00350               | ((uint64_t)m_hh << 40));
00351     }
00352 
00353   operator uint64_t() const
00354     { return val(); }
00355 
00356 private:
00357   ata_register & m_ll, & m_lm, & m_lh,
00358                & m_hl, & m_hm, & m_hh;
00359 
00360   // References must not be copied.
00361   ata_reg_alias_48(const ata_reg_alias_48 &);
00362   void operator=(const ata_reg_alias_48 &);
00363 };
00364 
00365 
00366 /// ATA Input registers for 48-bit commands
00367 // See section 4.14 of T13/1532D Volume 1 Revision 4b
00368 //
00369 // Uses ATA-6/7 method to specify 16-bit registers as
00370 // recent (low byte) and previous (high byte) content of
00371 // 8-bit registers.
00372 //
00373 // (ATA-8 ACS does not longer follow this scheme, it uses
00374 // abstract registers with sufficient size and leaves the
00375 // actual mapping to the transport layer.)
00376 //
00377 struct ata_in_regs_48bit
00378 : public ata_in_regs   // "most recently written" registers
00379 {
00380   ata_in_regs prev;  ///< "previous content"
00381 
00382   // 16-bit aliases for above pair.
00383   ata_reg_alias_16 features_16;
00384   ata_reg_alias_16 sector_count_16;
00385   ata_reg_alias_16 lba_low_16;
00386   ata_reg_alias_16 lba_mid_16;
00387   ata_reg_alias_16 lba_high_16;
00388 
00389   // 48-bit alias to all 8-bit LBA registers.
00390   ata_reg_alias_48 lba_48;
00391 
00392   /// Return true if 48-bit command
00393   bool is_48bit_cmd() const
00394     { return prev.is_set(); }
00395 
00396   /// Return true if 48-bit command with any nonzero high byte
00397   bool is_real_48bit_cmd() const
00398     { return (   prev.features || prev.sector_count
00399               || prev.lba_low || prev.lba_mid || prev.lba_high); }
00400 
00401   ata_in_regs_48bit();
00402 };
00403 
00404 
00405 /// ATA Output registers for 48-bit commands
00406 struct ata_out_regs_48bit
00407 : public ata_out_regs   // read with HOB=0
00408 {
00409   ata_out_regs prev;  ///< read with HOB=1
00410 
00411   // 16-bit aliases for above pair.
00412   ata_reg_alias_16 sector_count_16;
00413   ata_reg_alias_16 lba_low_16;
00414   ata_reg_alias_16 lba_mid_16;
00415   ata_reg_alias_16 lba_high_16;
00416 
00417   // 48-bit alias to all 8-bit LBA registers.
00418   ata_reg_alias_48 lba_48;
00419 
00420   ata_out_regs_48bit();
00421 };
00422 
00423 
00424 /// Flags for each ATA output register
00425 struct ata_out_regs_flags
00426 {
00427   bool error, sector_count, lba_low, lba_mid, lba_high, device, status;
00428 
00429   /// Return true if any flag is set.
00430   bool is_set() const
00431     { return (   error || sector_count || lba_low
00432               || lba_mid || lba_high || device || status); }
00433 
00434   /// Default constructor clears all flags.
00435   ata_out_regs_flags()
00436     : error(false), sector_count(false), lba_low(false), lba_mid(false),
00437       lba_high(false), device(false), status(false) { }
00438 };
00439 
00440 
00441 /// ATA pass through input parameters
00442 struct ata_cmd_in
00443 {
00444   ata_in_regs_48bit in_regs;  ///< Input registers
00445   ata_out_regs_flags out_needed; ///< True if output register value needed
00446   enum { no_data = 0, data_in, data_out } direction; ///< I/O direction
00447   void * buffer; ///< Pointer to data buffer
00448   unsigned size; ///< Size of buffer
00449 
00450   /// Prepare for 28-bit DATA IN command
00451   void set_data_in(void * buf, unsigned nsectors)
00452     {
00453       buffer = buf;
00454       in_regs.sector_count = nsectors;
00455       direction = data_in;
00456       size = nsectors * 512;
00457     }
00458 
00459   /// Prepare for 28-bit DATA OUT command
00460   void set_data_out(const void * buf, unsigned nsectors)
00461     {
00462       buffer = const_cast<void *>(buf);
00463       in_regs.sector_count = nsectors;
00464       direction = data_out;
00465       size = nsectors * 512;
00466     }
00467 
00468   /// Prepare for 48-bit DATA IN command
00469   void set_data_in_48bit(void * buf, unsigned nsectors)
00470     {
00471       buffer = buf;
00472       // Note: This also sets 'in_regs.is_48bit_cmd()'
00473       in_regs.sector_count_16 = nsectors;
00474       direction = data_in;
00475       size = nsectors * 512;
00476     }
00477 
00478   ata_cmd_in();
00479 };
00480 
00481 /// ATA pass through output parameters
00482 struct ata_cmd_out
00483 {
00484   ata_out_regs_48bit out_regs; ///< Output registers
00485 
00486   ata_cmd_out();
00487 };
00488 
00489 /// ATA device access
00490 class ata_device
00491 : virtual public /*extends*/ smart_device
00492 {
00493 public:
00494   /// ATA pass through.
00495   /// Return false on error.
00496   /// Must be implemented in derived class.
00497   virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) = 0;
00498 
00499   /// ATA pass through without output registers.
00500   /// Return false on error.
00501   /// Calls ata_pass_through(in, dummy), cannot be reimplemented.
00502   bool ata_pass_through(const ata_cmd_in & in);
00503 
00504   /// Return true if OS caches ATA identify sector.
00505   /// Default implementation returns false.
00506   virtual bool ata_identify_is_cached() const;
00507 
00508 protected:
00509   /// Flags for ata_cmd_is_supported().
00510   enum {
00511     supports_data_out = 0x01, // PIO DATA OUT
00512     supports_smart_status = 0x02, // read output registers for SMART STATUS only
00513     supports_output_regs = 0x04, // read output registers for all commands
00514     supports_multi_sector = 0x08, // more than one sector (1 DRQ/sector variant)
00515     supports_48bit_hi_null = 0x10, // 48-bit commands with null high bytes only
00516     supports_48bit = 0x20, // all 48-bit commands
00517   };
00518 
00519   /// Check command input parameters.
00520   /// Return false if required features are not implemented.
00521   /// Calls set_err(...) accordingly.
00522   bool ata_cmd_is_supported(const ata_cmd_in & in, unsigned flags,
00523     const char * type = 0);
00524 
00525   /// Check command input parameters (old version).
00526   // TODO: Remove if no longer used.
00527   bool ata_cmd_is_ok(const ata_cmd_in & in,
00528     bool data_out_support = false,
00529     bool multi_sector_support = false,
00530     bool ata_48bit_support = false)
00531     {
00532       return ata_cmd_is_supported(in,
00533         (data_out_support ? supports_data_out : 0) |
00534         supports_output_regs |
00535         (multi_sector_support ? supports_multi_sector : 0) |
00536         (ata_48bit_support ? supports_48bit : 0));
00537     }
00538 
00539   /// Hide/unhide ATA interface.
00540   void hide_ata(bool hide = true)
00541     { m_ata_ptr = (!hide ? this : 0); }
00542 
00543   /// Default constructor, registers device as ATA.
00544   ata_device()
00545     : smart_device(never_called)
00546     { hide_ata(false); }
00547 };
00548 
00549 
00550 /////////////////////////////////////////////////////////////////////////////
00551 // SCSI specific interface
00552 
00553 struct scsi_cmnd_io;
00554 
00555 /// SCSI device access
00556 class scsi_device
00557 : virtual public /*extends*/ smart_device
00558 {
00559 public:
00560   /// SCSI pass through.
00561   /// Returns false on error.
00562   virtual bool scsi_pass_through(scsi_cmnd_io * iop) = 0;
00563 
00564 protected:
00565   /// Hide/unhide SCSI interface.
00566   void hide_scsi(bool hide = true)
00567     { m_scsi_ptr = (!hide ? this : 0); }
00568 
00569   /// Default constructor, registers device as SCSI.
00570   scsi_device()
00571     : smart_device(never_called)
00572     { hide_scsi(false); }
00573 };
00574 
00575 
00576 /////////////////////////////////////////////////////////////////////////////
00577 /// Smart pointer class for device pointers
00578 
00579 template <class Dev>
00580 class any_device_auto_ptr
00581 {
00582 public:
00583   typedef Dev device_type;
00584 
00585   /// Construct from optional pointer to device
00586   /// and optional pointer to base device.
00587   explicit any_device_auto_ptr(device_type * dev = 0,
00588                                smart_device * base_dev = 0)
00589     : m_dev(dev), m_base_dev(base_dev) { }
00590 
00591   /// Destructor deletes device object.
00592   ~any_device_auto_ptr() throw()
00593     { reset(); }
00594 
00595   /// Assign a new pointer.
00596   /// Throws if a pointer is already assigned.
00597   void operator=(device_type * dev)
00598     {
00599       if (m_dev)
00600         fail();
00601       m_dev = dev;
00602     }
00603 
00604   /// Delete device object and clear the pointer.
00605   void reset()
00606     {
00607       if (m_dev) {
00608         if (m_base_dev && m_dev->owns(m_base_dev))
00609           m_dev->release(m_base_dev);
00610         delete m_dev;
00611         m_dev = 0;
00612       }
00613     }
00614 
00615   /// Return the pointer and release ownership.
00616   device_type * release()
00617     {
00618       device_type * dev = m_dev;
00619       m_dev = 0;
00620       return dev;
00621     }
00622 
00623   /// Replace the pointer.
00624   /// Used to call dev->autodetect_open().
00625   void replace(device_type * dev)
00626     { m_dev = dev; }
00627 
00628   /// Return the pointer.
00629   device_type * get() const
00630     { return m_dev; }
00631 
00632   /// Pointer dereferencing.
00633   device_type & operator*() const
00634     { return *m_dev; }
00635 
00636   /// Pointer dereferencing.
00637   device_type * operator->() const
00638     { return m_dev; }
00639 
00640   /// For (ptr != 0) check.
00641   operator bool() const
00642     { return !!m_dev; }
00643 
00644   /// For (ptr == 0) check.
00645   bool operator !() const
00646     { return !m_dev; }
00647 
00648 private:
00649   device_type * m_dev;
00650   smart_device * m_base_dev;
00651 
00652   void fail() const
00653     { throw std::logic_error("any_device_auto_ptr: wrong usage"); }
00654 
00655   // Prevent copy/assignment
00656   any_device_auto_ptr(const any_device_auto_ptr<Dev> &);
00657   void operator=(const any_device_auto_ptr<Dev> &);
00658 };
00659 
00660 typedef any_device_auto_ptr<smart_device> smart_device_auto_ptr;
00661 typedef any_device_auto_ptr<ata_device>   ata_device_auto_ptr;
00662 typedef any_device_auto_ptr<scsi_device>  scsi_device_auto_ptr;
00663 
00664 
00665 /////////////////////////////////////////////////////////////////////////////
00666 // smart_device_list
00667 
00668 /// List of devices for DEVICESCAN
00669 class smart_device_list
00670 {
00671 // Construction
00672 public:
00673   smart_device_list()
00674     { }
00675 
00676   ~smart_device_list() throw()
00677     {
00678       for (unsigned i = 0; i < m_list.size(); i++)
00679         delete m_list[i];
00680     }
00681 
00682 // Attributes
00683   unsigned size() const
00684     { return m_list.size(); }
00685 
00686 // Operations
00687   void clear()
00688     {
00689       for (unsigned i = 0; i < m_list.size(); i++)
00690         delete m_list[i];
00691       m_list.clear();
00692     }
00693 
00694 
00695   void push_back(smart_device * dev)
00696     { m_list.push_back(dev); }
00697 
00698   void push_back(smart_device_auto_ptr & dev)
00699     {
00700       m_list.push_back(dev.get());
00701       dev.release();
00702     }
00703 
00704   smart_device * at(unsigned i)
00705     { return m_list.at(i); }
00706 
00707   const smart_device * at(unsigned i) const
00708     { return m_list.at(i); }
00709 
00710   smart_device * release(unsigned i)
00711     {
00712       smart_device * dev = m_list.at(i);
00713       m_list[i] = 0;
00714       return dev;
00715     }
00716 
00717 // Implementation
00718 private:
00719   std::vector<smart_device *> m_list;
00720 
00721   // Prevent copy/assigment
00722   smart_device_list(const smart_device_list &);
00723   void operator=(const smart_device_list &);
00724 };
00725 
00726 
00727 /////////////////////////////////////////////////////////////////////////////
00728 // smart_interface
00729 
00730 /// The platform interface abstraction
00731 class smart_interface
00732 {
00733 public:
00734   /// Initialize platform interface and register with smi().
00735   /// Must be implemented by platform module and register interface with set()
00736   static void init();
00737 
00738   smart_interface()
00739     { }
00740 
00741   virtual ~smart_interface() throw()
00742     { }
00743 
00744   /// Return info string about build host and/or OS version.
00745   /// Default implementation returns SMARTMONTOOLS_BUILD_HOST.
00746   virtual std::string get_os_version_str();
00747 
00748   /// Return valid args for device type option/directive.
00749   /// Default implementation returns "ata, scsi, sat, usb*..."
00750   /// concatenated with result from get_valid_custom_dev_types_str().
00751   virtual std::string get_valid_dev_types_str();
00752 
00753   /// Return example string for program 'appname'.
00754   /// Default implementation returns empty string.
00755   /// For the migration of print_smartctl_examples(),
00756   /// function is allowed to print examples to stdout.
00757   /// TODO: Remove this hack.
00758   virtual std::string get_app_examples(const char * appname);
00759 
00760   /// Get microseconds since some unspecified starting point.
00761   /// Used only for command duration measurements in debug outputs.
00762   /// Returns -1 if unsupported.
00763   /// Default implementation uses clock_gettime(), gettimeofday() or ftime().
00764   virtual int64_t get_timer_usec();
00765 
00766   /// Disable/Enable system auto standby/sleep mode.
00767   /// Return false if unsupported or if system is running
00768   /// on battery.
00769   /// Default implementation returns false.
00770   virtual bool disable_system_auto_standby(bool disable);
00771 
00772 
00773   ///////////////////////////////////////////////
00774   // Last error information
00775 
00776   /// Get last error info struct.
00777   const smart_device::error_info & get_err() const
00778     { return m_err; }
00779   /// Get last error number.
00780   int get_errno() const
00781     { return m_err.no; }
00782   /// Get last error message.
00783   const char * get_errmsg() const
00784     { return m_err.msg.c_str(); }
00785 
00786   /// Set last error number and message.
00787   /// Printf()-like formatting is supported.
00788   /// Returns false always to allow use as a return expression.
00789   bool set_err(int no, const char * msg, ...)
00790     __attribute_format_printf(3, 4);
00791 
00792   /// Set last error info struct.
00793   bool set_err(const smart_device::error_info & err)
00794     { m_err = err; return false; }
00795 
00796   /// Clear last error info.
00797   void clear_err()
00798     { m_err.clear(); }
00799 
00800   /// Set last error number and default message.
00801   /// Message is retrieved from get_msg_for_errno(no).
00802   bool set_err(int no);
00803 
00804   /// Set last error number and default message to any error_info.
00805   /// Used by set_err(no).
00806   bool set_err_var(smart_device::error_info * err, int no);
00807 
00808   /// Convert error number into message, used by set_err(no).
00809   /// Default implementation returns strerror(no).
00810   virtual const char * get_msg_for_errno(int no);
00811 
00812   ///////////////////////////////////////////////////////////////////////////
00813   // Device factory:
00814 
00815   /// Return device object for device 'name' with some 'type'.
00816   /// 'type' is 0 if not specified by user.
00817   /// Return 0 on error.
00818   /// Default implementation selects between ata, scsi and custom device.
00819   virtual smart_device * get_smart_device(const char * name, const char * type);
00820 
00821   /// Fill 'devlist' with devices of some 'type' with device names
00822   /// specified by some optional 'pattern'.
00823   /// Return false on error.
00824   virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
00825     const char * pattern = 0) = 0;
00826 
00827 protected:
00828   /// Return standard ATA device.
00829   virtual ata_device * get_ata_device(const char * name, const char * type) = 0;
00830 
00831   /// Return standard SCSI device.
00832   virtual scsi_device * get_scsi_device(const char * name, const char * type) = 0;
00833 
00834   /// Autodetect device if no device type specified.
00835   virtual smart_device * autodetect_smart_device(const char * name) = 0;
00836 
00837   /// Return device for platform specific 'type'.
00838   /// Default implementation returns 0.
00839   virtual smart_device * get_custom_smart_device(const char * name, const char * type);
00840 
00841   /// Return valid 'type' args accepted by above.
00842   /// This is called in get_valid_dev_types_str().
00843   /// Default implementation returns empty string.
00844   virtual std::string get_valid_custom_dev_types_str();
00845 
00846   /// Return ATA->SCSI filter for SAT or USB.
00847   /// Override only if platform needs special handling.
00848   virtual ata_device * get_sat_device(const char * type, scsi_device * scsidev);
00849   //{ implemented in scsiata.cpp }
00850 
00851 public:
00852   /// Try to detect a SAT device behind a SCSI interface.
00853   /// Inquiry data can be passed if available.
00854   /// Return appropriate device if yes, otherwise 0.
00855   /// Override only if platform needs special handling.
00856   virtual ata_device * autodetect_sat_device(scsi_device * scsidev,
00857     const unsigned char * inqdata, unsigned inqsize);
00858   //{ implemented in scsiata.cpp }
00859 
00860   /// Get type name for USB device with known VENDOR:PRODUCT ID.
00861   /// Return name if device known and supported, otherwise 0.
00862   virtual const char * get_usb_dev_type_by_id(int vendor_id, int product_id,
00863                                               int version = -1);
00864   //{ implemented in scsiata.cpp }
00865 
00866 protected:
00867   /// Set interface to use, must be called from init().
00868   static void set(smart_interface * intf)
00869     { s_instance = intf; }
00870 
00871 // Implementation
00872 private:
00873   smart_device::error_info m_err;
00874 
00875   friend smart_interface * smi(); // below
00876   static smart_interface * s_instance; ///< Pointer to the interface object.
00877 
00878   // Prevent copy/assigment
00879   smart_interface(const smart_interface &);
00880   void operator=(const smart_interface &);
00881 };
00882 
00883 
00884 /////////////////////////////////////////////////////////////////////////////
00885 // smi()
00886 
00887 /// Global access to the (usually singleton) smart_interface
00888 inline smart_interface * smi()
00889   { return smart_interface::s_instance; }
00890 
00891 /////////////////////////////////////////////////////////////////////////////
00892 
00893 #endif // DEV_INTERFACE_H