4 * Home page of code is: http://www.smartmontools.org
6 * Copyright (C) 2008-18 Christian Franke
8 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include "dev_interface.h"
17 #include "dev_ata_cmd_set.h"
21 const char * dev_legacy_cpp_cvsid
= "$Id: dev_legacy.cpp 4760 2018-08-19 18:45:53Z chrfranke $"
22 DEV_INTERFACE_H_CVSID
;
24 /////////////////////////////////////////////////////////////////////////////
26 // Legacy interface declarations (now commented out globally):
29 int guess_device_type(const char * dev_name
);
30 int make_device_names (char ***devlist
, const char* name
);
31 int deviceopen(const char *pathname
, char *type
);
32 int deviceclose(int fd
);
35 int ata_command_interface(int device
, smart_command_set command
, int select
, char *data
);
38 int do_scsi_cmnd_io(int dev_fd
, struct scsi_cmnd_io
* iop
, int report
);
41 void print_smartctl_examples();
43 /////////////////////////////////////////////////////////////////////////////
45 namespace os
{ // No need to publish anything, name provided for Doxygen
47 /////////////////////////////////////////////////////////////////////////////
48 /// Implement shared open/close routines with old functions.
50 class legacy_smart_device
51 : virtual public /*implements*/ smart_device
54 explicit legacy_smart_device(const char * mode
)
55 : smart_device(never_called
),
56 m_fd(-1), m_mode(mode
) { }
58 virtual ~legacy_smart_device() throw();
60 virtual bool is_open() const;
67 /// Return filedesc for derived classes.
72 int m_fd
; ///< filedesc, -1 if not open.
73 const char * m_mode
; ///< Mode string for deviceopen().
77 legacy_smart_device::~legacy_smart_device() throw()
83 bool legacy_smart_device::is_open() const
88 bool legacy_smart_device::open()
90 m_fd
= ::deviceopen(get_dev_name(), const_cast<char*>(m_mode
));
92 set_err((errno
==ENOENT
|| errno
==ENOTDIR
) ? ENODEV
: errno
);
98 bool legacy_smart_device::close()
100 int fd
= m_fd
; m_fd
= -1;
101 if (::deviceclose(fd
) < 0) {
108 /////////////////////////////////////////////////////////////////////////////
109 /// Implement standard ATA support with old functions
111 class legacy_ata_device
112 : public /*implements*/ ata_device_with_command_set
,
113 public /*extends*/ legacy_smart_device
116 legacy_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
119 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
122 legacy_ata_device::legacy_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
123 : smart_device(intf
, dev_name
, "ata", req_type
),
124 legacy_smart_device("ATA")
128 int legacy_ata_device::ata_command_interface(smart_command_set command
, int select
, char * data
)
130 return ::ata_command_interface(get_fd(), command
, select
, data
);
134 /////////////////////////////////////////////////////////////////////////////
135 /// Implement standard SCSI support with old functions
137 class legacy_scsi_device
138 : public /*implements*/ scsi_device
,
139 public /*extends*/ legacy_smart_device
142 legacy_scsi_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
144 virtual smart_device
* autodetect_open();
146 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
149 legacy_scsi_device::legacy_scsi_device(smart_interface
* intf
,
150 const char * dev_name
, const char * req_type
)
151 : smart_device(intf
, dev_name
, "scsi", req_type
),
152 legacy_smart_device("SCSI")
156 bool legacy_scsi_device::scsi_pass_through(scsi_cmnd_io
* iop
)
158 int status
= ::do_scsi_cmnd_io(get_fd(), iop
, scsi_debugmode
);
167 /////////////////////////////////////////////////////////////////////////////
168 /// SCSI open with autodetection support
170 smart_device
* legacy_scsi_device::autodetect_open()
176 // No Autodetection if device type was specified by user
180 // The code below is based on smartd.cpp:SCSIFilterKnown()
183 unsigned char req_buff
[64] = {0, };
185 if (scsiStdInquiry(this, req_buff
, req_len
)) {
186 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
187 // watch this spot ... other devices could lock up here
189 if (scsiStdInquiry(this, req_buff
, req_len
)) {
190 // device doesn't like INQUIRY commands
192 set_err(EIO
, "INQUIRY failed");
197 int avail_len
= req_buff
[4] + 5;
198 int len
= (avail_len
< req_len
? avail_len
: req_len
);
202 // Use INQUIRY to detect type
206 smart_device
* newdev
= smi()->autodetect_sat_device(this, req_buff
, len
);
208 // NOTE: 'this' is now owned by '*newdev'
212 // Nothing special found
217 /////////////////////////////////////////////////////////////////////////////
218 /// Implement platform interface with old functions.
220 class legacy_smart_interface
221 : public /*implements*/ smart_interface
224 virtual std::string
get_app_examples(const char * appname
);
226 virtual bool scan_smart_devices(smart_device_list
& devlist
, const char * type
,
227 const char * pattern
= 0);
230 virtual ata_device
* get_ata_device(const char * name
, const char * type
);
232 virtual scsi_device
* get_scsi_device(const char * name
, const char * type
);
234 virtual smart_device
* autodetect_smart_device(const char * name
);
238 //////////////////////////////////////////////////////////////////////
240 std::string
legacy_smart_interface::get_app_examples(const char * appname
)
242 if (!strcmp(appname
, "smartctl"))
243 ::print_smartctl_examples(); // this prints to stdout ...
244 return ""; // ... so don't print again.
247 ata_device
* legacy_smart_interface::get_ata_device(const char * name
, const char * type
)
249 return new legacy_ata_device(this, name
, type
);
252 scsi_device
* legacy_smart_interface::get_scsi_device(const char * name
, const char * type
)
254 return new legacy_scsi_device(this, name
, type
);
258 smart_device
* legacy_smart_interface::autodetect_smart_device(const char * name
)
260 switch (::guess_device_type(name
)) {
261 case CONTROLLER_ATA
: return new legacy_ata_device(this, name
, "");
262 case CONTROLLER_SCSI
: return new legacy_scsi_device(this, name
, "");
264 // TODO: Test autodetect device here
269 static void free_devnames(char * * devnames
, int numdevs
)
273 for (int i
= 0; i
< numdevs
; i
++) {
280 bool legacy_smart_interface::scan_smart_devices(smart_device_list
& devlist
,
281 const char * type
, const char * pattern
/*= 0*/)
284 set_err(EINVAL
, "DEVICESCAN with pattern not implemented yet");
289 char * * atanames
= 0; int numata
= 0;
290 if (!type
|| !strcmp(type
, "ata")) {
291 numata
= ::make_device_names(&atanames
, "ATA");
298 char * * scsinames
= 0; int numscsi
= 0;
299 if (!type
|| !strcmp(type
, "scsi")) {
300 numscsi
= ::make_device_names(&scsinames
, "SCSI");
302 free_devnames(atanames
, numata
);
312 for (i
= 0; i
< numata
; i
++) {
313 ata_device
* atadev
= get_ata_device(atanames
[i
], type
);
315 devlist
.push_back(atadev
);
317 free_devnames(atanames
, numata
);
319 for (i
= 0; i
< numscsi
; i
++) {
320 scsi_device
* scsidev
= get_scsi_device(scsinames
[i
], type
);
322 devlist
.push_back(scsidev
);
324 free_devnames(scsinames
, numscsi
);
331 /////////////////////////////////////////////////////////////////////////////
332 /// Initialize platform interface and register with smi()
334 void smart_interface::init()
336 static os::legacy_smart_interface the_interface
;
337 smart_interface::set(&the_interface
);