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