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