Annotation of embedaddon/smartmontools/dev_interface.h, revision 1.1.1.3

1.1       misho       1: /*
                      2:  * dev_interface.h
                      3:  *
                      4:  * Home page of code is: http://smartmontools.sourceforge.net
                      5:  *
1.1.1.2   misho       6:  * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
1.1       misho       7:  *
                      8:  * This program is free software; you can redistribute it and/or modify
                      9:  * it under the terms of the GNU General Public License as published by
                     10:  * the Free Software Foundation; either version 2, or (at your option)
                     11:  * any later version.
                     12:  *
                     13:  * You should have received a copy of the GNU General Public License
                     14:  * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
                     15:  *
                     16:  */
                     17: 
                     18: #ifndef DEV_INTERFACE_H
                     19: #define DEV_INTERFACE_H
                     20: 
1.1.1.3 ! misho      21: #define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 3663 2012-10-24 20:35:55Z chrfranke $\n"
1.1.1.2   misho      22: 
                     23: #include "utility.h"
1.1       misho      24: 
                     25: #include <stdexcept>
                     26: #include <string>
                     27: #include <vector>
                     28: 
                     29: /////////////////////////////////////////////////////////////////////////////
                     30: // Common functionality for all device types
                     31: 
                     32: // Forward declarations
                     33: class smart_interface;
                     34: class ata_device;
                     35: class scsi_device;
                     36: 
                     37: /// Base class for all devices
                     38: class smart_device
                     39: {
                     40: // Types
                     41: public:
                     42:   /// Device info strings
                     43:   struct device_info {
                     44:     device_info()
                     45:       { }
                     46:     device_info(const char * d_name, const char * d_type, const char * r_type)
                     47:       : dev_name(d_name), info_name(d_name),
                     48:         dev_type(d_type), req_type(r_type)
                     49:       { }
                     50: 
                     51:     std::string dev_name;  ///< Device (path)name
                     52:     std::string info_name; ///< Informal name
                     53:     std::string dev_type;  ///< Actual device type
                     54:     std::string req_type;  ///< Device type requested by user, empty if none
                     55:   };
                     56: 
                     57:   /// Error (number,message) pair
                     58:   struct error_info {
                     59:     explicit error_info(int n = 0)
                     60:       : no(n) { }
                     61:     error_info(int n, const char * m)
                     62:       : no(n), msg(m) { }
                     63:     void clear()
                     64:       { no = 0; msg.erase(); }
                     65: 
                     66:     int no;          ///< Error number
                     67:     std::string msg; ///< Error message
                     68:   };
                     69: 
                     70: // Construction
                     71: protected:
                     72:   /// Constructor to init interface and device info.
                     73:   /// Must be called in implementation classes.
                     74:   smart_device(smart_interface * intf, const char * dev_name,
                     75:     const char * dev_type, const char * req_type);
                     76: 
                     77:   /// Dummy enum for dummy constructor.
                     78:   enum do_not_use_in_implementation_classes { never_called };
                     79:   /// Dummy constructor for abstract classes.
                     80:   /// Must never be called in implementation classes.
                     81:   smart_device(do_not_use_in_implementation_classes);
                     82: 
                     83: public:
                     84:   virtual ~smart_device() throw();
                     85: 
                     86: // Attributes
                     87: public:
                     88:   ///////////////////////////////////////////////
                     89:   // Dynamic downcasts to actual device flavor
                     90: 
                     91:   /// Return true if ATA device
                     92:   bool is_ata() const
                     93:     { return !!m_ata_ptr; }
                     94:   /// Return true if SCSI device
                     95:   bool is_scsi() const
                     96:     { return !!m_scsi_ptr; }
                     97: 
                     98:   /// Downcast to ATA device.
                     99:   ata_device * to_ata()
                    100:     { return m_ata_ptr; }
                    101:   /// Downcast to ATA device (const).
                    102:   const ata_device * to_ata() const
                    103:     { return m_ata_ptr; }
                    104:   /// Downcast to SCSI device.
                    105:   scsi_device * to_scsi()
                    106:     { return m_scsi_ptr; }
                    107:   /// Downcast to SCSI device (const).
                    108:   const scsi_device * to_scsi() const
                    109:     { return m_scsi_ptr; }
                    110: 
                    111:   ///////////////////////////////////////////////
                    112:   // Device information
                    113: 
                    114:   /// Get device info struct.
                    115:   const device_info & get_info() const
                    116:     { return m_info; }
                    117: 
                    118:   /// Get device (path)name.
                    119:   const char * get_dev_name() const
                    120:     { return m_info.dev_name.c_str(); }
                    121:   /// Get informal name.
                    122:   const char * get_info_name() const
                    123:     { return m_info.info_name.c_str(); }
                    124:   /// Get device type.
                    125:   const char * get_dev_type() const
                    126:     { return m_info.dev_type.c_str(); }
                    127:   /// Get type requested by user, empty if none.
                    128:   const char * get_req_type() const
                    129:     { return m_info.req_type.c_str(); }
                    130: 
                    131: protected:
                    132:   /// R/W access to device info struct.
                    133:   device_info & set_info()
                    134:     { return m_info; }
                    135: 
                    136: public:
                    137:   ///////////////////////////////////////////////
                    138:   // Last error information
                    139: 
                    140:   /// Get last error info struct.
                    141:   const error_info & get_err() const
                    142:     { return m_err; }
                    143:   /// Get last error number.
                    144:   int get_errno() const
                    145:     { return m_err.no; }
                    146:   /// Get last error message.
                    147:   const char * get_errmsg() const
                    148:     { return m_err.msg.c_str(); }
                    149: 
1.1.1.2   misho     150:   /// Return true if last error indicates an unsupported system call.
                    151:   /// Default implementation returns true on ENOSYS and ENOTSUP.
                    152:   virtual bool is_syscall_unsup() const;
                    153: 
1.1       misho     154:   /// Set last error number and message.
                    155:   /// Printf()-like formatting is supported.
                    156:   /// Returns false always to allow use as a return expression.
                    157:   bool set_err(int no, const char * msg, ...)
1.1.1.2   misho     158:     __attribute_format_printf(3, 4);
1.1       misho     159: 
                    160:   /// Set last error info struct.
                    161:   bool set_err(const error_info & err)
                    162:     { m_err = err; return false; }
                    163: 
                    164:   /// Clear last error info.
                    165:   void clear_err()
                    166:     { m_err.clear(); }
                    167: 
                    168:   /// Set last error number and default message.
                    169:   /// Message is retrieved from interface's get_msg_for_errno(no).
                    170:   bool set_err(int no);
                    171: 
                    172: // Operations
                    173: public:
                    174:   ///////////////////////////////////////////////
                    175:   // Device open/close
                    176:   // Must be implemented in derived class
                    177: 
                    178:   /// Return true if device is open.
                    179:   virtual bool is_open() const = 0;
                    180: 
                    181:   /// Open device, return false on error.
                    182:   virtual bool open() = 0;
                    183: 
                    184:   /// Close device, return false on error.
                    185:   virtual bool close() = 0;
                    186: 
                    187:   /// Open device with autodetection support.
                    188:   /// May return another device for further access.
                    189:   /// In this case, the original pointer is no longer valid.
1.1.1.2   misho     190:   /// Default implementation calls 'open()' and returns 'this'.
1.1       misho     191:   virtual smart_device * autodetect_open();
                    192: 
                    193:   ///////////////////////////////////////////////
                    194:   // Support for tunnelled devices
                    195: 
                    196:   /// Return true if other device is owned by this device.
                    197:   /// Default implementation returns false.
                    198:   virtual bool owns(const smart_device * dev) const;
                    199: 
                    200:   /// Release ownership of other device.
                    201:   /// Default implementation does nothing.
                    202:   virtual void release(const smart_device * dev);
                    203: 
                    204: protected:
                    205:   /// Get interface which produced this object.
                    206:   smart_interface * smi()
                    207:     { return m_intf; }
                    208:   /// Get interface which produced this object (const).
                    209:   const smart_interface * smi() const
                    210:     { return m_intf; }
                    211: 
                    212: // Implementation
                    213: private:
                    214:   smart_interface * m_intf;
                    215:   device_info m_info;
1.1.1.2   misho     216:   error_info m_err;
                    217: 
                    218:   // Pointers for to_ata(), to_scsi(),
                    219:   // set by ATA/SCSI interface classes.
                    220:   friend class ata_device;
1.1       misho     221:   ata_device * m_ata_ptr;
1.1.1.2   misho     222:   friend class scsi_device;
1.1       misho     223:   scsi_device * m_scsi_ptr;
                    224: 
                    225:   // Prevent copy/assigment
                    226:   smart_device(const smart_device &);
                    227:   void operator=(const smart_device &);
                    228: };
                    229: 
                    230: 
                    231: /////////////////////////////////////////////////////////////////////////////
                    232: // ATA specific interface
                    233: 
                    234: /// ATA register value and info whether it has ever been set
                    235: // (Automatically set by first assignment)
                    236: class ata_register
                    237: {
                    238: public:
                    239:   ata_register()
                    240:     : m_val(0x00), m_is_set(false) { }
                    241: 
                    242:   ata_register & operator=(unsigned char x)
                    243:     { m_val = x; m_is_set = true; return * this; }
                    244: 
                    245:   unsigned char val() const
                    246:     { return m_val; }
                    247:   operator unsigned char() const
                    248:     { return m_val; }
                    249: 
                    250:   bool is_set() const
                    251:     { return m_is_set; }
                    252: 
                    253: private:
                    254:   unsigned char m_val; ///< Register value
                    255:   bool m_is_set; ///< true if set
                    256: };
                    257: 
                    258: /// ATA Input registers (for 28-bit commands)
                    259: struct ata_in_regs
                    260: {
                    261:   // ATA-6/7 register names  // ATA-3/4/5        // ATA-8
                    262:   ata_register features;     // features         // features
                    263:   ata_register sector_count; // sector count     // count
                    264:   ata_register lba_low;      // sector number    // ]
                    265:   ata_register lba_mid;      // cylinder low     // ] lba
                    266:   ata_register lba_high;     // cylinder high    // ]
                    267:   ata_register device;       // device/head      // device
                    268:   ata_register command;      // command          // command
                    269: 
                    270:   /// Return true if any register is set
                    271:   bool is_set() const
                    272:     { return (features.is_set() || sector_count.is_set()
                    273:       || lba_low.is_set() || lba_mid.is_set() || lba_high.is_set()
                    274:       || device.is_set() || command.is_set());                    }
                    275: };
                    276: 
                    277: /// ATA Output registers (for 28-bit commands)
                    278: struct ata_out_regs
                    279: {
                    280:   ata_register error;
                    281:   ata_register sector_count;
                    282:   ata_register lba_low;
                    283:   ata_register lba_mid;
                    284:   ata_register lba_high;
                    285:   ata_register device;
                    286:   ata_register status;
                    287: 
                    288:   /// Return true if any register is set
                    289:   bool is_set() const
                    290:     { return (error.is_set() || sector_count.is_set()
                    291:       || lba_low.is_set() || lba_mid.is_set() || lba_high.is_set()
                    292:       || device.is_set() || status.is_set());                      }
                    293: };
                    294: 
                    295: 
                    296: /// 16-bit alias to a 8-bit ATA register pair.
                    297: class ata_reg_alias_16
                    298: {
                    299: public:
                    300:   ata_reg_alias_16(ata_register & lo, ata_register & hi)
                    301:     : m_lo(lo), m_hi(hi) { }
                    302: 
                    303:   ata_reg_alias_16 & operator=(unsigned short x)
                    304:     { m_lo = (unsigned char) x;
                    305:       m_hi = (unsigned char)(x >> 8);
                    306:       return * this;                   }
                    307: 
                    308:   unsigned short val() const
                    309:     { return m_lo | (m_hi << 8); }
                    310:   operator unsigned short() const
                    311:     { return m_lo | (m_hi << 8); }
                    312: 
                    313: private:
                    314:   ata_register & m_lo, & m_hi;
                    315: 
                    316:   // References must not be copied.
                    317:   ata_reg_alias_16(const ata_reg_alias_16 &);
                    318:   void operator=(const ata_reg_alias_16 &);
                    319: };
                    320: 
                    321: 
                    322: /// 48-bit alias to six 8-bit ATA registers (for LBA).
                    323: class ata_reg_alias_48
                    324: {
                    325: public:
                    326:   ata_reg_alias_48(ata_register & ll, ata_register & lm, ata_register & lh,
                    327:                    ata_register & hl, ata_register & hm, ata_register & hh)
                    328:     : m_ll(ll), m_lm(lm), m_lh(lh),
                    329:       m_hl(hl), m_hm(hm), m_hh(hh)
                    330:     { }
                    331: 
                    332:   ata_reg_alias_48 & operator=(uint64_t x)
                    333:     {
                    334:       m_ll = (unsigned char) x;
                    335:       m_lm = (unsigned char)(x >>  8);
                    336:       m_lh = (unsigned char)(x >> 16);
                    337:       m_hl = (unsigned char)(x >> 24);
                    338:       m_hm = (unsigned char)(x >> 32);
                    339:       m_hh = (unsigned char)(x >> 40);
                    340:       return * this;
                    341:     }
                    342: 
                    343:   uint64_t val() const
                    344:     {
                    345:       return (   (unsigned)m_ll
                    346:               | ((unsigned)m_lm <<  8)
                    347:               | ((unsigned)m_lh << 16)
                    348:               | ((unsigned)m_hl << 24)
                    349:               | ((uint64_t)m_hm << 32)
                    350:               | ((uint64_t)m_hh << 40));
                    351:     }
                    352: 
                    353:   operator uint64_t() const
                    354:     { return val(); }
                    355: 
                    356: private:
                    357:   ata_register & m_ll, & m_lm, & m_lh,
                    358:                & m_hl, & m_hm, & m_hh;
                    359: 
                    360:   // References must not be copied.
                    361:   ata_reg_alias_48(const ata_reg_alias_48 &);
                    362:   void operator=(const ata_reg_alias_48 &);
                    363: };
                    364: 
                    365: 
                    366: /// ATA Input registers for 48-bit commands
                    367: // See section 4.14 of T13/1532D Volume 1 Revision 4b
                    368: //
                    369: // Uses ATA-6/7 method to specify 16-bit registers as
                    370: // recent (low byte) and previous (high byte) content of
                    371: // 8-bit registers.
                    372: //
                    373: // (ATA-8 ACS does not longer follow this scheme, it uses
                    374: // abstract registers with sufficient size and leaves the
                    375: // actual mapping to the transport layer.)
                    376: //
                    377: struct ata_in_regs_48bit
                    378: : public ata_in_regs   // "most recently written" registers
                    379: {
                    380:   ata_in_regs prev;  ///< "previous content"
                    381: 
                    382:   // 16-bit aliases for above pair.
                    383:   ata_reg_alias_16 features_16;
                    384:   ata_reg_alias_16 sector_count_16;
                    385:   ata_reg_alias_16 lba_low_16;
                    386:   ata_reg_alias_16 lba_mid_16;
                    387:   ata_reg_alias_16 lba_high_16;
                    388: 
                    389:   // 48-bit alias to all 8-bit LBA registers.
                    390:   ata_reg_alias_48 lba_48;
                    391: 
                    392:   /// Return true if 48-bit command
                    393:   bool is_48bit_cmd() const
                    394:     { return prev.is_set(); }
                    395: 
                    396:   /// Return true if 48-bit command with any nonzero high byte
                    397:   bool is_real_48bit_cmd() const
                    398:     { return (   prev.features || prev.sector_count
                    399:               || prev.lba_low || prev.lba_mid || prev.lba_high); }
                    400: 
                    401:   ata_in_regs_48bit();
                    402: };
                    403: 
                    404: 
                    405: /// ATA Output registers for 48-bit commands
                    406: struct ata_out_regs_48bit
                    407: : public ata_out_regs   // read with HOB=0
                    408: {
                    409:   ata_out_regs prev;  ///< read with HOB=1
                    410: 
                    411:   // 16-bit aliases for above pair.
                    412:   ata_reg_alias_16 sector_count_16;
                    413:   ata_reg_alias_16 lba_low_16;
                    414:   ata_reg_alias_16 lba_mid_16;
                    415:   ata_reg_alias_16 lba_high_16;
                    416: 
                    417:   // 48-bit alias to all 8-bit LBA registers.
                    418:   ata_reg_alias_48 lba_48;
                    419: 
                    420:   ata_out_regs_48bit();
                    421: };
                    422: 
                    423: 
                    424: /// Flags for each ATA output register
                    425: struct ata_out_regs_flags
                    426: {
                    427:   bool error, sector_count, lba_low, lba_mid, lba_high, device, status;
                    428: 
                    429:   /// Return true if any flag is set.
                    430:   bool is_set() const
                    431:     { return (   error || sector_count || lba_low
                    432:               || lba_mid || lba_high || device || status); }
                    433: 
                    434:   /// Default constructor clears all flags.
                    435:   ata_out_regs_flags()
                    436:     : error(false), sector_count(false), lba_low(false), lba_mid(false),
                    437:       lba_high(false), device(false), status(false) { }
                    438: };
                    439: 
                    440: 
                    441: /// ATA pass through input parameters
                    442: struct ata_cmd_in
                    443: {
                    444:   ata_in_regs_48bit in_regs;  ///< Input registers
                    445:   ata_out_regs_flags out_needed; ///< True if output register value needed
                    446:   enum { no_data = 0, data_in, data_out } direction; ///< I/O direction
                    447:   void * buffer; ///< Pointer to data buffer
                    448:   unsigned size; ///< Size of buffer
                    449: 
                    450:   /// Prepare for 28-bit DATA IN command
                    451:   void set_data_in(void * buf, unsigned nsectors)
                    452:     {
                    453:       buffer = buf;
                    454:       in_regs.sector_count = nsectors;
                    455:       direction = data_in;
                    456:       size = nsectors * 512;
                    457:     }
                    458: 
                    459:   /// Prepare for 28-bit DATA OUT command
                    460:   void set_data_out(const void * buf, unsigned nsectors)
                    461:     {
                    462:       buffer = const_cast<void *>(buf);
                    463:       in_regs.sector_count = nsectors;
                    464:       direction = data_out;
                    465:       size = nsectors * 512;
                    466:     }
                    467: 
                    468:   /// Prepare for 48-bit DATA IN command
                    469:   void set_data_in_48bit(void * buf, unsigned nsectors)
                    470:     {
                    471:       buffer = buf;
                    472:       // Note: This also sets 'in_regs.is_48bit_cmd()'
                    473:       in_regs.sector_count_16 = nsectors;
                    474:       direction = data_in;
                    475:       size = nsectors * 512;
                    476:     }
                    477: 
                    478:   ata_cmd_in();
                    479: };
                    480: 
                    481: /// ATA pass through output parameters
                    482: struct ata_cmd_out
                    483: {
                    484:   ata_out_regs_48bit out_regs; ///< Output registers
                    485: 
                    486:   ata_cmd_out();
                    487: };
                    488: 
                    489: /// ATA device access
                    490: class ata_device
                    491: : virtual public /*extends*/ smart_device
                    492: {
                    493: public:
                    494:   /// ATA pass through.
                    495:   /// Return false on error.
                    496:   /// Must be implemented in derived class.
                    497:   virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) = 0;
                    498: 
                    499:   /// ATA pass through without output registers.
                    500:   /// Return false on error.
                    501:   /// Calls ata_pass_through(in, dummy), cannot be reimplemented.
                    502:   bool ata_pass_through(const ata_cmd_in & in);
                    503: 
                    504:   /// Return true if OS caches ATA identify sector.
                    505:   /// Default implementation returns false.
                    506:   virtual bool ata_identify_is_cached() const;
                    507: 
                    508: protected:
1.1.1.3 ! misho     509:   /// Flags for ata_cmd_is_supported().
        !           510:   enum {
        !           511:     supports_data_out = 0x01, // PIO DATA OUT
        !           512:     supports_smart_status = 0x02, // read output registers for SMART STATUS only
        !           513:     supports_output_regs = 0x04, // read output registers for all commands
        !           514:     supports_multi_sector = 0x08, // more than one sector (1 DRQ/sector variant)
        !           515:     supports_48bit_hi_null = 0x10, // 48-bit commands with null high bytes only
        !           516:     supports_48bit = 0x20, // all 48-bit commands
        !           517:   };
        !           518: 
1.1       misho     519:   /// Check command input parameters.
1.1.1.3 ! misho     520:   /// Return false if required features are not implemented.
1.1       misho     521:   /// Calls set_err(...) accordingly.
1.1.1.3 ! misho     522:   bool ata_cmd_is_supported(const ata_cmd_in & in, unsigned flags,
        !           523:     const char * type = 0);
        !           524: 
        !           525:   /// Check command input parameters (old version).
        !           526:   // TODO: Remove if no longer used.
1.1       misho     527:   bool ata_cmd_is_ok(const ata_cmd_in & in,
                    528:     bool data_out_support = false,
                    529:     bool multi_sector_support = false,
1.1.1.3 ! misho     530:     bool ata_48bit_support = false)
        !           531:     {
        !           532:       return ata_cmd_is_supported(in,
        !           533:         (data_out_support ? supports_data_out : 0) |
        !           534:         supports_output_regs |
        !           535:         (multi_sector_support ? supports_multi_sector : 0) |
        !           536:         (ata_48bit_support ? supports_48bit : 0));
        !           537:     }
1.1       misho     538: 
1.1.1.2   misho     539:   /// Hide/unhide ATA interface.
                    540:   void hide_ata(bool hide = true)
                    541:     { m_ata_ptr = (!hide ? this : 0); }
                    542: 
1.1       misho     543:   /// Default constructor, registers device as ATA.
                    544:   ata_device()
                    545:     : smart_device(never_called)
1.1.1.2   misho     546:     { hide_ata(false); }
1.1       misho     547: };
                    548: 
                    549: 
                    550: /////////////////////////////////////////////////////////////////////////////
                    551: // SCSI specific interface
                    552: 
                    553: struct scsi_cmnd_io;
                    554: 
                    555: /// SCSI device access
                    556: class scsi_device
                    557: : virtual public /*extends*/ smart_device
                    558: {
                    559: public:
                    560:   /// SCSI pass through.
                    561:   /// Returns false on error.
                    562:   virtual bool scsi_pass_through(scsi_cmnd_io * iop) = 0;
                    563: 
                    564: protected:
1.1.1.2   misho     565:   /// Hide/unhide SCSI interface.
                    566:   void hide_scsi(bool hide = true)
                    567:     { m_scsi_ptr = (!hide ? this : 0); }
                    568: 
1.1       misho     569:   /// Default constructor, registers device as SCSI.
                    570:   scsi_device()
                    571:     : smart_device(never_called)
1.1.1.2   misho     572:     { hide_scsi(false); }
1.1       misho     573: };
                    574: 
                    575: 
                    576: /////////////////////////////////////////////////////////////////////////////
                    577: /// Smart pointer class for device pointers
                    578: 
                    579: template <class Dev>
                    580: class any_device_auto_ptr
                    581: {
                    582: public:
                    583:   typedef Dev device_type;
                    584: 
                    585:   /// Construct from optional pointer to device
                    586:   /// and optional pointer to base device.
                    587:   explicit any_device_auto_ptr(device_type * dev = 0,
                    588:                                smart_device * base_dev = 0)
                    589:     : m_dev(dev), m_base_dev(base_dev) { }
                    590: 
                    591:   /// Destructor deletes device object.
                    592:   ~any_device_auto_ptr() throw()
                    593:     { reset(); }
                    594: 
                    595:   /// Assign a new pointer.
                    596:   /// Throws if a pointer is already assigned.
                    597:   void operator=(device_type * dev)
                    598:     {
                    599:       if (m_dev)
                    600:         fail();
                    601:       m_dev = dev;
                    602:     }
                    603: 
                    604:   /// Delete device object and clear the pointer.
                    605:   void reset()
                    606:     {
                    607:       if (m_dev) {
                    608:         if (m_base_dev && m_dev->owns(m_base_dev))
                    609:           m_dev->release(m_base_dev);
                    610:         delete m_dev;
                    611:         m_dev = 0;
                    612:       }
                    613:     }
                    614: 
                    615:   /// Return the pointer and release ownership.
                    616:   device_type * release()
                    617:     {
                    618:       device_type * dev = m_dev;
                    619:       m_dev = 0;
                    620:       return dev;
                    621:     }
                    622: 
                    623:   /// Replace the pointer.
                    624:   /// Used to call dev->autodetect_open().
                    625:   void replace(device_type * dev)
                    626:     { m_dev = dev; }
                    627: 
                    628:   /// Return the pointer.
                    629:   device_type * get() const
                    630:     { return m_dev; }
                    631: 
                    632:   /// Pointer dereferencing.
                    633:   device_type & operator*() const
                    634:     { return *m_dev; }
                    635: 
                    636:   /// Pointer dereferencing.
                    637:   device_type * operator->() const
                    638:     { return m_dev; }
                    639: 
                    640:   /// For (ptr != 0) check.
                    641:   operator bool() const
                    642:     { return !!m_dev; }
                    643: 
                    644:   /// For (ptr == 0) check.
                    645:   bool operator !() const
                    646:     { return !m_dev; }
                    647: 
                    648: private:
                    649:   device_type * m_dev;
                    650:   smart_device * m_base_dev;
                    651: 
                    652:   void fail() const
                    653:     { throw std::logic_error("any_device_auto_ptr: wrong usage"); }
                    654: 
                    655:   // Prevent copy/assignment
                    656:   any_device_auto_ptr(const any_device_auto_ptr<Dev> &);
                    657:   void operator=(const any_device_auto_ptr<Dev> &);
                    658: };
                    659: 
                    660: typedef any_device_auto_ptr<smart_device> smart_device_auto_ptr;
                    661: typedef any_device_auto_ptr<ata_device>   ata_device_auto_ptr;
                    662: typedef any_device_auto_ptr<scsi_device>  scsi_device_auto_ptr;
                    663: 
                    664: 
                    665: /////////////////////////////////////////////////////////////////////////////
                    666: // smart_device_list
                    667: 
                    668: /// List of devices for DEVICESCAN
                    669: class smart_device_list
                    670: {
                    671: // Construction
                    672: public:
                    673:   smart_device_list()
                    674:     { }
                    675: 
                    676:   ~smart_device_list() throw()
                    677:     {
                    678:       for (unsigned i = 0; i < m_list.size(); i++)
                    679:         delete m_list[i];
                    680:     }
                    681: 
                    682: // Attributes
                    683:   unsigned size() const
                    684:     { return m_list.size(); }
                    685: 
                    686: // Operations
                    687:   void clear()
                    688:     {
                    689:       for (unsigned i = 0; i < m_list.size(); i++)
                    690:         delete m_list[i];
                    691:       m_list.clear();
                    692:     }
                    693: 
                    694: 
                    695:   void push_back(smart_device * dev)
                    696:     { m_list.push_back(dev); }
                    697: 
                    698:   void push_back(smart_device_auto_ptr & dev)
                    699:     {
                    700:       m_list.push_back(dev.get());
                    701:       dev.release();
                    702:     }
                    703: 
                    704:   smart_device * at(unsigned i)
                    705:     { return m_list.at(i); }
                    706: 
                    707:   const smart_device * at(unsigned i) const
                    708:     { return m_list.at(i); }
                    709: 
                    710:   smart_device * release(unsigned i)
                    711:     {
                    712:       smart_device * dev = m_list.at(i);
                    713:       m_list[i] = 0;
                    714:       return dev;
                    715:     }
                    716: 
                    717: // Implementation
                    718: private:
                    719:   std::vector<smart_device *> m_list;
                    720: 
                    721:   // Prevent copy/assigment
                    722:   smart_device_list(const smart_device_list &);
                    723:   void operator=(const smart_device_list &);
                    724: };
                    725: 
                    726: 
                    727: /////////////////////////////////////////////////////////////////////////////
                    728: // smart_interface
                    729: 
                    730: /// The platform interface abstraction
                    731: class smart_interface
                    732: {
                    733: public:
                    734:   /// Initialize platform interface and register with smi().
                    735:   /// Must be implemented by platform module and register interface with set()
                    736:   static void init();
                    737: 
                    738:   smart_interface()
                    739:     { }
                    740: 
                    741:   virtual ~smart_interface() throw()
                    742:     { }
                    743: 
                    744:   /// Return info string about build host and/or OS version.
                    745:   /// Default implementation returns SMARTMONTOOLS_BUILD_HOST.
                    746:   virtual std::string get_os_version_str();
                    747: 
                    748:   /// Return valid args for device type option/directive.
                    749:   /// Default implementation returns "ata, scsi, sat, usb*..."
                    750:   /// concatenated with result from get_valid_custom_dev_types_str().
                    751:   virtual std::string get_valid_dev_types_str();
                    752: 
                    753:   /// Return example string for program 'appname'.
                    754:   /// Default implementation returns empty string.
                    755:   /// For the migration of print_smartctl_examples(),
                    756:   /// function is allowed to print examples to stdout.
                    757:   /// TODO: Remove this hack.
                    758:   virtual std::string get_app_examples(const char * appname);
                    759: 
1.1.1.2   misho     760:   /// Get microseconds since some unspecified starting point.
                    761:   /// Used only for command duration measurements in debug outputs.
                    762:   /// Returns -1 if unsupported.
                    763:   /// Default implementation uses clock_gettime(), gettimeofday() or ftime().
                    764:   virtual int64_t get_timer_usec();
                    765: 
                    766:   /// Disable/Enable system auto standby/sleep mode.
                    767:   /// Return false if unsupported or if system is running
                    768:   /// on battery.
                    769:   /// Default implementation returns false.
                    770:   virtual bool disable_system_auto_standby(bool disable);
                    771: 
                    772: 
1.1       misho     773:   ///////////////////////////////////////////////
                    774:   // Last error information
                    775: 
                    776:   /// Get last error info struct.
                    777:   const smart_device::error_info & get_err() const
                    778:     { return m_err; }
                    779:   /// Get last error number.
                    780:   int get_errno() const
                    781:     { return m_err.no; }
                    782:   /// Get last error message.
                    783:   const char * get_errmsg() const
                    784:     { return m_err.msg.c_str(); }
                    785: 
                    786:   /// Set last error number and message.
                    787:   /// Printf()-like formatting is supported.
1.1.1.2   misho     788:   /// Returns false always to allow use as a return expression.
                    789:   bool set_err(int no, const char * msg, ...)
                    790:     __attribute_format_printf(3, 4);
1.1       misho     791: 
                    792:   /// Set last error info struct.
1.1.1.2   misho     793:   bool set_err(const smart_device::error_info & err)
                    794:     { m_err = err; return false; }
1.1       misho     795: 
                    796:   /// Clear last error info.
                    797:   void clear_err()
                    798:     { m_err.clear(); }
                    799: 
                    800:   /// Set last error number and default message.
                    801:   /// Message is retrieved from get_msg_for_errno(no).
1.1.1.2   misho     802:   bool set_err(int no);
1.1       misho     803: 
                    804:   /// Set last error number and default message to any error_info.
                    805:   /// Used by set_err(no).
1.1.1.2   misho     806:   bool set_err_var(smart_device::error_info * err, int no);
1.1       misho     807: 
                    808:   /// Convert error number into message, used by set_err(no).
                    809:   /// Default implementation returns strerror(no).
                    810:   virtual const char * get_msg_for_errno(int no);
                    811: 
                    812:   ///////////////////////////////////////////////////////////////////////////
                    813:   // Device factory:
                    814: 
                    815:   /// Return device object for device 'name' with some 'type'.
                    816:   /// 'type' is 0 if not specified by user.
                    817:   /// Return 0 on error.
                    818:   /// Default implementation selects between ata, scsi and custom device.
                    819:   virtual smart_device * get_smart_device(const char * name, const char * type);
                    820: 
                    821:   /// Fill 'devlist' with devices of some 'type' with device names
                    822:   /// specified by some optional 'pattern'.
                    823:   /// Return false on error.
                    824:   virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
                    825:     const char * pattern = 0) = 0;
                    826: 
                    827: protected:
                    828:   /// Return standard ATA device.
                    829:   virtual ata_device * get_ata_device(const char * name, const char * type) = 0;
                    830: 
                    831:   /// Return standard SCSI device.
                    832:   virtual scsi_device * get_scsi_device(const char * name, const char * type) = 0;
                    833: 
                    834:   /// Autodetect device if no device type specified.
                    835:   virtual smart_device * autodetect_smart_device(const char * name) = 0;
                    836: 
                    837:   /// Return device for platform specific 'type'.
                    838:   /// Default implementation returns 0.
                    839:   virtual smart_device * get_custom_smart_device(const char * name, const char * type);
                    840: 
                    841:   /// Return valid 'type' args accepted by above.
                    842:   /// This is called in get_valid_dev_types_str().
                    843:   /// Default implementation returns empty string.
                    844:   virtual std::string get_valid_custom_dev_types_str();
                    845: 
                    846:   /// Return ATA->SCSI filter for SAT or USB.
                    847:   /// Override only if platform needs special handling.
                    848:   virtual ata_device * get_sat_device(const char * type, scsi_device * scsidev);
                    849:   //{ implemented in scsiata.cpp }
                    850: 
                    851: public:
                    852:   /// Try to detect a SAT device behind a SCSI interface.
                    853:   /// Inquiry data can be passed if available.
                    854:   /// Return appropriate device if yes, otherwise 0.
                    855:   /// Override only if platform needs special handling.
                    856:   virtual ata_device * autodetect_sat_device(scsi_device * scsidev,
                    857:     const unsigned char * inqdata, unsigned inqsize);
                    858:   //{ implemented in scsiata.cpp }
                    859: 
                    860:   /// Get type name for USB device with known VENDOR:PRODUCT ID.
                    861:   /// Return name if device known and supported, otherwise 0.
                    862:   virtual const char * get_usb_dev_type_by_id(int vendor_id, int product_id,
                    863:                                               int version = -1);
                    864:   //{ implemented in scsiata.cpp }
                    865: 
                    866: protected:
                    867:   /// Set interface to use, must be called from init().
                    868:   static void set(smart_interface * intf)
                    869:     { s_instance = intf; }
                    870: 
                    871: // Implementation
                    872: private:
                    873:   smart_device::error_info m_err;
                    874: 
                    875:   friend smart_interface * smi(); // below
                    876:   static smart_interface * s_instance; ///< Pointer to the interface object.
                    877: 
                    878:   // Prevent copy/assigment
                    879:   smart_interface(const smart_interface &);
                    880:   void operator=(const smart_interface &);
                    881: };
                    882: 
                    883: 
                    884: /////////////////////////////////////////////////////////////////////////////
                    885: // smi()
                    886: 
                    887: /// Global access to the (usually singleton) smart_interface
                    888: inline smart_interface * smi()
                    889:   { return smart_interface::s_instance; }
                    890: 
                    891: /////////////////////////////////////////////////////////////////////////////
                    892: 
                    893: #endif // DEV_INTERFACE_H

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>