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
13 #include "dev_interface.h"
14 #include "dev_intelliprop.h"
15 #include "dev_tunnelled.h"
16 #include "atacmds.h" // ATA_SMART_CMD/STATUS
17 #include "scsicmds.h" // scsi_cmnd_io
24 #if defined(HAVE_GETTIMEOFDAY)
26 #elif defined(HAVE_FTIME)
27 #include <sys/timeb.h>
30 const char * dev_interface_cpp_cvsid
= "$Id: dev_interface.cpp 4848 2018-12-05 18:30:46Z chrfranke $"
31 DEV_INTERFACE_H_CVSID
;
33 /////////////////////////////////////////////////////////////////////////////
36 int smart_device::s_num_objects
= 0;
38 smart_device::smart_device(smart_interface
* intf
, const char * dev_name
,
39 const char * dev_type
, const char * req_type
)
40 : m_intf(intf
), m_info(dev_name
, dev_type
, req_type
),
41 m_ata_ptr(0), m_scsi_ptr(0), m_nvme_ptr(0)
46 smart_device::smart_device(do_not_use_in_implementation_classes
)
47 : m_intf(0), m_ata_ptr(0), m_scsi_ptr(0), m_nvme_ptr(0)
49 throw std::logic_error("smart_device: wrong constructor called in implementation class");
52 smart_device::~smart_device() throw()
57 bool smart_device::is_syscall_unsup() const
59 if (get_errno() == ENOSYS
)
62 if (get_errno() == ENOTSUP
)
68 bool smart_device::set_err(int no
, const char * msg
, ...)
73 va_list ap
; va_start(ap
, msg
);
74 m_err
.msg
= vstrprintf(msg
, ap
);
79 bool smart_device::set_err(int no
)
81 return smi()->set_err_var(&m_err
, no
);
84 smart_device
* smart_device::autodetect_open()
90 bool smart_device::is_powered_down()
95 bool smart_device::owns(const smart_device
* /*dev*/) const
100 void smart_device::release(const smart_device
* /*dev*/)
105 /////////////////////////////////////////////////////////////////////////////
108 ata_in_regs_48bit::ata_in_regs_48bit()
109 : features_16(features
, prev
.features
),
110 sector_count_16(sector_count
, prev
.sector_count
),
111 lba_low_16(lba_low
, prev
.lba_low
),
112 lba_mid_16(lba_mid
, prev
.lba_mid
),
113 lba_high_16(lba_high
, prev
.lba_high
),
114 lba_48( lba_low
, lba_mid
, lba_high
,
115 prev
.lba_low
, prev
.lba_mid
, prev
.lba_high
)
119 ata_out_regs_48bit::ata_out_regs_48bit()
120 : sector_count_16(sector_count
, prev
.sector_count
),
121 lba_low_16(lba_low
, prev
.lba_low
),
122 lba_mid_16(lba_mid
, prev
.lba_mid
),
123 lba_high_16(lba_high
, prev
.lba_high
),
124 lba_48( lba_low
, lba_mid
, lba_high
,
125 prev
.lba_low
, prev
.lba_mid
, prev
.lba_high
)
129 ata_cmd_in::ata_cmd_in()
130 : direction(no_data
),
136 ata_cmd_out::ata_cmd_out()
140 bool ata_device::ata_pass_through(const ata_cmd_in
& in
)
143 return ata_pass_through(in
, dummy
);
146 bool ata_device::ata_cmd_is_supported(const ata_cmd_in
& in
,
147 unsigned flags
, const char * type
/* = 0 */)
150 switch (in
.direction
) {
151 case ata_cmd_in::no_data
: break;
152 case ata_cmd_in::data_in
: break;
153 case ata_cmd_in::data_out
: break;
155 return set_err(EINVAL
, "Invalid data direction %d", (int)in
.direction
);
159 if (in
.direction
== ata_cmd_in::no_data
) {
161 return set_err(EINVAL
, "Buffer size %u > 0 for NO DATA command", in
.size
);
165 return set_err(EINVAL
, "Buffer not set for DATA IN/OUT command");
166 unsigned count
= (in
.in_regs
.prev
.sector_count
<<16)|in
.in_regs
.sector_count
;
167 // TODO: Add check for sector count == 0
168 if (count
* 512 != in
.size
)
169 return set_err(EINVAL
, "Sector count %u does not match buffer size %u", count
, in
.size
);
173 const char * errmsg
= 0;
174 if (in
.direction
== ata_cmd_in::data_out
&& !(flags
& supports_data_out
))
175 errmsg
= "DATA OUT ATA commands not implemented";
176 else if ( in
.out_needed
.is_set() && !(flags
& supports_output_regs
)
177 && !( in
.in_regs
.command
== ATA_SMART_CMD
178 && in
.in_regs
.features
== ATA_SMART_STATUS
179 && (flags
& supports_smart_status
)))
180 errmsg
= "Read of ATA output registers not implemented";
181 else if (!(in
.size
== 0 || in
.size
== 512) && !(flags
& supports_multi_sector
))
182 errmsg
= "Multi-sector ATA commands not implemented";
183 else if (in
.in_regs
.is_48bit_cmd() && !(flags
& (supports_48bit_hi_null
|supports_48bit
)))
184 errmsg
= "48-bit ATA commands not implemented";
185 else if (in
.in_regs
.is_real_48bit_cmd() && !(flags
& supports_48bit
))
186 errmsg
= "48-bit ATA commands not fully implemented";
189 return set_err(ENOSYS
, "%s%s%s%s", errmsg
,
190 (type
? " [" : ""), (type
? type
: ""), (type
? "]" : ""));
195 bool ata_device::ata_identify_is_cached() const
200 /////////////////////////////////////////////////////////////////////////////
203 bool scsi_device::scsi_pass_through_and_check(scsi_cmnd_io
* iop
,
206 // Provide sense buffer
207 unsigned char sense
[32] = {0, };
209 iop
->max_sense_len
= sizeof(sense
);
210 iop
->timeout
= SCSI_TIMEOUT_DEFAULT
;
213 if (!scsi_pass_through(iop
)) {
214 if (scsi_debugmode
> 0)
215 pout("%sscsi_pass_through() failed, errno=%d [%s]\n",
216 msg
, get_errno(), get_errmsg());
221 scsi_sense_disect sinfo
;
222 scsi_do_sense_disect(iop
, &sinfo
);
223 int err
= scsiSimpleSenseFilter(&sinfo
);
225 if (scsi_debugmode
> 0)
226 pout("%sscsi error: %s\n", msg
, scsiErrString(err
));
227 return set_err(EIO
, "scsi error %s", scsiErrString(err
));
233 /////////////////////////////////////////////////////////////////////////////
236 bool nvme_device::set_nvme_err(nvme_cmd_out
& out
, unsigned status
, const char * msg
/* = 0 */)
239 throw std::logic_error("nvme_device: set_nvme_err() called with status=0");
242 out
.status_valid
= true;
243 return set_err(EIO
, "%sNVMe Status 0x%02x", (msg
? msg
: ""), status
);
247 /////////////////////////////////////////////////////////////////////////////
248 // tunnelled_device_base
250 tunnelled_device_base::tunnelled_device_base(smart_device
* tunnel_dev
)
251 : smart_device(never_called
),
252 m_tunnel_base_dev(tunnel_dev
)
256 tunnelled_device_base::~tunnelled_device_base() throw()
258 delete m_tunnel_base_dev
;
261 bool tunnelled_device_base::is_open() const
263 return (m_tunnel_base_dev
&& m_tunnel_base_dev
->is_open());
266 bool tunnelled_device_base::open()
268 if (!m_tunnel_base_dev
)
269 return set_err(ENOSYS
);
270 if (!m_tunnel_base_dev
->open())
271 return set_err(m_tunnel_base_dev
->get_err());
275 bool tunnelled_device_base::close()
277 if (!m_tunnel_base_dev
)
279 if (!m_tunnel_base_dev
->close())
280 return set_err(m_tunnel_base_dev
->get_err());
284 bool tunnelled_device_base::owns(const smart_device
* dev
) const
286 return (m_tunnel_base_dev
&& (m_tunnel_base_dev
== dev
));
289 void tunnelled_device_base::release(const smart_device
* dev
)
291 if (m_tunnel_base_dev
== dev
)
292 m_tunnel_base_dev
= 0;
296 /////////////////////////////////////////////////////////////////////////////
299 // Pointer to (usually singleton) interface object returned by ::smi()
300 smart_interface
* smart_interface::s_instance
;
302 std::string
smart_interface::get_os_version_str()
304 return SMARTMONTOOLS_BUILD_HOST
;
307 std::string
smart_interface::get_valid_dev_types_str()
311 "ata, scsi[+TYPE], nvme[,NSID], sat[,auto][,N][+TYPE], usbcypress[,X], "
312 "usbjmicron[,p][,x][,N], usbprolific, usbsunplus, sntjmicron[,NSID], "
313 "intelliprop,N[+TYPE]";
315 std::string s2
= get_valid_custom_dev_types_str();
322 std::string
smart_interface::get_app_examples(const char * /*appname*/)
327 int64_t smart_interface::get_timer_usec()
329 #if defined(HAVE_GETTIMEOFDAY)
330 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
332 static bool have_clock_monotonic
= true;
333 if (have_clock_monotonic
) {
335 if (!clock_gettime(CLOCK_MONOTONIC
, &ts
))
336 return ts
.tv_sec
* 1000000LL + ts
.tv_nsec
/1000;
337 have_clock_monotonic
= false;
343 gettimeofday(&tv
, 0);
344 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
346 #elif defined(HAVE_FTIME)
350 return tb
.time
* 1000000LL + tb
.millitm
* 1000;
357 bool smart_interface::disable_system_auto_standby(bool /*disable*/)
359 return set_err(ENOSYS
);
362 bool smart_interface::set_err(int no
, const char * msg
, ...)
367 va_list ap
; va_start(ap
, msg
);
368 m_err
.msg
= vstrprintf(msg
, ap
);
373 bool smart_interface::set_err(int no
)
375 return set_err_var(&m_err
, no
);
378 bool smart_interface::set_err_var(smart_device::error_info
* err
, int no
)
381 err
->msg
= get_msg_for_errno(no
);
382 if (err
->msg
.empty() && no
!= 0)
383 err
->msg
= strprintf("Unknown error %d", no
);
387 const char * smart_interface::get_msg_for_errno(int no
)
393 /////////////////////////////////////////////////////////////////////////////
394 // Default device factory
396 smart_device
* smart_interface::get_smart_device(const char * name
, const char * type
)
400 // Call platform specific autodetection if no device type specified
402 if (!type
|| !*type
) {
403 dev
= autodetect_smart_device(name
);
404 if (!dev
&& !get_errno())
405 set_err(EINVAL
, "Unable to detect device type");
409 // First check for platform specific device types
410 dev
= get_custom_smart_device(name
, type
);
411 if (dev
|| get_errno())
414 if (!strcmp(type
, "ata"))
415 dev
= get_ata_device(name
, type
);
416 else if (!strcmp(type
, "scsi"))
417 dev
= get_scsi_device(name
, type
);
419 else if (str_starts_with(type
, "nvme")) {
420 int n1
= -1, n2
= -1, len
= strlen(type
);
421 unsigned nsid
= 0; // invalid namespace id -> use default
422 sscanf(type
, "nvme%n,0x%x%n", &n1
, &nsid
, &n2
);
423 if (!(n1
== len
|| n2
== len
)) {
424 set_err(EINVAL
, "Invalid NVMe namespace id in '%s'", type
);
427 dev
= get_nvme_device(name
, type
, nsid
);
430 else if ( (str_starts_with(type
, "sat") && (!type
[3] || strchr(",+", type
[3])))
431 || str_starts_with(type
, "scsi+")
432 || str_starts_with(type
, "usb") ) {
433 // Split "sat...+base..." -> ("sat...", "base...")
434 unsigned satlen
= strcspn(type
, "+");
435 std::string
sattype(type
, satlen
);
436 const char * basetype
= (type
[satlen
] ? type
+satlen
+1 : "");
437 // Recurse to allocate base device, default is standard SCSI
440 smart_device_auto_ptr
basedev( get_smart_device(name
, basetype
) );
442 set_err(EINVAL
, "Type '%s+...': %s", sattype
.c_str(), get_errmsg());
445 // Result must be SCSI
446 if (!basedev
->is_scsi()) {
447 set_err(EINVAL
, "Type '%s+...': Device type '%s' is not SCSI", sattype
.c_str(), basetype
);
451 return get_sat_device(sattype
.c_str(), basedev
.release()->to_scsi());
454 else if (str_starts_with(type
, "snt")) {
455 smart_device_auto_ptr
basedev( get_smart_device(name
, "scsi") );
457 set_err(EINVAL
, "Type '%s': %s", type
, get_errmsg());
461 return get_snt_device(type
, basedev
.release()->to_scsi());
464 else if (str_starts_with(type
, "intelliprop")) {
465 // Parse "intelliprop,N[+base...]"
466 unsigned phydrive
= ~0; int n
= -1; char c
= 0;
467 sscanf(type
, "intelliprop,%u%n%c", &phydrive
, &n
, &c
);
468 if (!((n
== (int)strlen(type
) || c
== '+') && phydrive
<= 3)) {
469 set_err(EINVAL
, "Option '-d intelliprop,N' requires N between 0 and 3");
472 const char * basetype
= (type
[n
] ? type
+ n
+ 1 : "");
473 // Recurse to allocate base device, default is standard ATA
476 smart_device_auto_ptr
basedev( get_smart_device(name
, basetype
) );
478 set_err(EINVAL
, "Type '%s': %s", type
, get_errmsg());
481 // Result must be ATA
482 if (!basedev
->is_ata()) {
483 set_err(EINVAL
, "Type '%s': Device type '%s' is not ATA", type
, basetype
);
486 return get_intelliprop_device(this, phydrive
, basedev
.release()->to_ata());
490 set_err(EINVAL
, "Unknown device type '%s'", type
);
493 if (!dev
&& !get_errno())
494 set_err(EINVAL
, "Not a device of type '%s'", type
);
498 bool smart_interface::scan_smart_devices(smart_device_list
& /*devlist*/,
499 const char * /*type*/, const char * /*pattern*/ /* = 0 */)
501 return set_err(ENOSYS
);
504 bool smart_interface::scan_smart_devices(smart_device_list
& devlist
,
505 const smart_devtype_list
& types
, const char * pattern
/* = 0 */)
507 unsigned n
= types
.size();
509 return scan_smart_devices(devlist
, (const char *)0, pattern
);
511 return scan_smart_devices(devlist
, types
.front().c_str(), pattern
);
513 for (unsigned i
= 0; i
< n
; i
++) {
514 smart_device_list tmplist
;
515 if (!scan_smart_devices(tmplist
, types
[i
].c_str(), pattern
))
517 devlist
.append(tmplist
);
523 nvme_device
* smart_interface::get_nvme_device(const char * /*name*/, const char * /*type*/, unsigned /*nsid*/)
525 set_err(ENOSYS
, "NVMe devices are not supported in this version of smartmontools");
529 smart_device
* smart_interface::get_custom_smart_device(const char * /*name*/, const char * /*type*/)
534 std::string
smart_interface::get_valid_custom_dev_types_str()
539 smart_device
* smart_interface::get_scsi_passthrough_device(const char * type
, scsi_device
* scsidev
)
541 if (!strncmp(type
, "snt", 3)) {
542 return get_snt_device(type
, scsidev
);
545 return get_sat_device(type
, scsidev
);