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

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

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