4 * Home page of code is: http://www.smartmontools.org
6 * Copyright (C) 2008-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
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)
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/>.
20 #include "dev_interface.h"
21 #include "dev_tunnelled.h"
22 #include "atacmds.h" // ATA_SMART_CMD/STATUS
29 #if defined(HAVE_GETTIMEOFDAY)
31 #elif defined(HAVE_FTIME)
32 #include <sys/timeb.h>
35 const char * dev_interface_cpp_cvsid
= "$Id: dev_interface.cpp 4120 2015-08-27 16:12:21Z samm2 $"
36 DEV_INTERFACE_H_CVSID
;
38 /////////////////////////////////////////////////////////////////////////////
41 smart_device::smart_device(smart_interface
* intf
, const char * dev_name
,
42 const char * dev_type
, const char * req_type
)
43 : m_intf(intf
), m_info(dev_name
, dev_type
, req_type
),
44 m_ata_ptr(0), m_scsi_ptr(0)
48 smart_device::smart_device(do_not_use_in_implementation_classes
)
49 : m_intf(0), m_ata_ptr(0), m_scsi_ptr(0)
51 throw std::logic_error("smart_device: wrong constructor called in implementation class");
54 smart_device::~smart_device() throw()
58 bool smart_device::is_syscall_unsup() const
60 if (get_errno() == ENOSYS
)
63 if (get_errno() == ENOTSUP
)
69 bool smart_device::set_err(int no
, const char * msg
, ...)
74 va_list ap
; va_start(ap
, msg
);
75 m_err
.msg
= vstrprintf(msg
, ap
);
80 bool smart_device::set_err(int no
)
82 return smi()->set_err_var(&m_err
, no
);
85 smart_device
* smart_device::autodetect_open()
91 bool smart_device::owns(const smart_device
* /*dev*/) const
96 void smart_device::release(const smart_device
* /*dev*/)
101 /////////////////////////////////////////////////////////////////////////////
104 ata_in_regs_48bit::ata_in_regs_48bit()
105 : features_16(features
, prev
.features
),
106 sector_count_16(sector_count
, prev
.sector_count
),
107 lba_low_16(lba_low
, prev
.lba_low
),
108 lba_mid_16(lba_mid
, prev
.lba_mid
),
109 lba_high_16(lba_high
, prev
.lba_high
),
110 lba_48( lba_low
, lba_mid
, lba_high
,
111 prev
.lba_low
, prev
.lba_mid
, prev
.lba_high
)
115 ata_out_regs_48bit::ata_out_regs_48bit()
116 : sector_count_16(sector_count
, prev
.sector_count
),
117 lba_low_16(lba_low
, prev
.lba_low
),
118 lba_mid_16(lba_mid
, prev
.lba_mid
),
119 lba_high_16(lba_high
, prev
.lba_high
),
120 lba_48( lba_low
, lba_mid
, lba_high
,
121 prev
.lba_low
, prev
.lba_mid
, prev
.lba_high
)
125 ata_cmd_in::ata_cmd_in()
126 : direction(no_data
),
132 ata_cmd_out::ata_cmd_out()
136 bool ata_device::ata_pass_through(const ata_cmd_in
& in
)
139 return ata_pass_through(in
, dummy
);
142 bool ata_device::ata_cmd_is_supported(const ata_cmd_in
& in
,
143 unsigned flags
, const char * type
/* = 0 */)
146 switch (in
.direction
) {
147 case ata_cmd_in::no_data
: break;
148 case ata_cmd_in::data_in
: break;
149 case ata_cmd_in::data_out
: break;
151 return set_err(EINVAL
, "Invalid data direction %d", (int)in
.direction
);
155 if (in
.direction
== ata_cmd_in::no_data
) {
157 return set_err(EINVAL
, "Buffer size %u > 0 for NO DATA command", in
.size
);
161 return set_err(EINVAL
, "Buffer not set for DATA IN/OUT command");
162 unsigned count
= (in
.in_regs
.prev
.sector_count
<<16)|in
.in_regs
.sector_count
;
163 // TODO: Add check for sector count == 0
164 if (count
* 512 != in
.size
)
165 return set_err(EINVAL
, "Sector count %u does not match buffer size %u", count
, in
.size
);
169 const char * errmsg
= 0;
170 if (in
.direction
== ata_cmd_in::data_out
&& !(flags
& supports_data_out
))
171 errmsg
= "DATA OUT ATA commands not implemented";
172 else if ( in
.out_needed
.is_set() && !(flags
& supports_output_regs
)
173 && !( in
.in_regs
.command
== ATA_SMART_CMD
174 && in
.in_regs
.features
== ATA_SMART_STATUS
175 && (flags
& supports_smart_status
)))
176 errmsg
= "Read of ATA output registers not implemented";
177 else if (!(in
.size
== 0 || in
.size
== 512) && !(flags
& supports_multi_sector
))
178 errmsg
= "Multi-sector ATA commands not implemented";
179 else if (in
.in_regs
.is_48bit_cmd() && !(flags
& (supports_48bit_hi_null
|supports_48bit
)))
180 errmsg
= "48-bit ATA commands not implemented";
181 else if (in
.in_regs
.is_real_48bit_cmd() && !(flags
& supports_48bit
))
182 errmsg
= "48-bit ATA commands not fully implemented";
185 return set_err(ENOSYS
, "%s%s%s%s", errmsg
,
186 (type
? " [" : ""), (type
? type
: ""), (type
? "]" : ""));
191 bool ata_device::ata_identify_is_cached() const
197 /////////////////////////////////////////////////////////////////////////////
198 // tunnelled_device_base
200 tunnelled_device_base::tunnelled_device_base(smart_device
* tunnel_dev
)
201 : smart_device(never_called
),
202 m_tunnel_base_dev(tunnel_dev
)
206 tunnelled_device_base::~tunnelled_device_base() throw()
208 delete m_tunnel_base_dev
;
211 bool tunnelled_device_base::is_open() const
213 return (m_tunnel_base_dev
&& m_tunnel_base_dev
->is_open());
216 bool tunnelled_device_base::open()
218 if (!m_tunnel_base_dev
)
219 return set_err(ENOSYS
);
220 if (!m_tunnel_base_dev
->open())
221 return set_err(m_tunnel_base_dev
->get_err());
225 bool tunnelled_device_base::close()
227 if (!m_tunnel_base_dev
)
229 if (!m_tunnel_base_dev
->close())
230 return set_err(m_tunnel_base_dev
->get_err());
234 bool tunnelled_device_base::owns(const smart_device
* dev
) const
236 return (m_tunnel_base_dev
&& (m_tunnel_base_dev
== dev
));
239 void tunnelled_device_base::release(const smart_device
* dev
)
241 if (m_tunnel_base_dev
== dev
)
242 m_tunnel_base_dev
= 0;
246 /////////////////////////////////////////////////////////////////////////////
249 // Pointer to (usually singleton) interface object returned by ::smi()
250 smart_interface
* smart_interface::s_instance
;
252 std::string
smart_interface::get_os_version_str()
254 return SMARTMONTOOLS_BUILD_HOST
;
257 std::string
smart_interface::get_valid_dev_types_str()
261 "ata, scsi, sat[,auto][,N][+TYPE], usbcypress[,X], usbjmicron[,p][,x][,N], usbsunplus";
263 std::string s2
= get_valid_custom_dev_types_str();
270 std::string
smart_interface::get_app_examples(const char * /*appname*/)
275 int64_t smart_interface::get_timer_usec()
277 #if defined(HAVE_GETTIMEOFDAY)
278 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
280 static bool have_clock_monotonic
= true;
281 if (have_clock_monotonic
) {
283 if (!clock_gettime(CLOCK_MONOTONIC
, &ts
))
284 return ts
.tv_sec
* 1000000LL + ts
.tv_nsec
/1000;
285 have_clock_monotonic
= false;
291 gettimeofday(&tv
, 0);
292 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
294 #elif defined(HAVE_FTIME)
298 return tb
.time
* 1000000LL + tb
.millitm
* 1000;
305 bool smart_interface::disable_system_auto_standby(bool /*disable*/)
307 return set_err(ENOSYS
);
310 bool smart_interface::set_err(int no
, const char * msg
, ...)
315 va_list ap
; va_start(ap
, msg
);
316 m_err
.msg
= vstrprintf(msg
, ap
);
321 bool smart_interface::set_err(int no
)
323 return set_err_var(&m_err
, no
);
326 bool smart_interface::set_err_var(smart_device::error_info
* err
, int no
)
329 err
->msg
= get_msg_for_errno(no
);
330 if (err
->msg
.empty() && no
!= 0)
331 err
->msg
= strprintf("Unknown error %d", no
);
335 const char * smart_interface::get_msg_for_errno(int no
)
341 /////////////////////////////////////////////////////////////////////////////
342 // Default device factory
344 smart_device
* smart_interface::get_smart_device(const char * name
, const char * type
)
348 // Call platform specific autodetection if no device type specified
350 if (!type
|| !*type
) {
351 dev
= autodetect_smart_device(name
);
352 if (!dev
&& !get_errno())
353 set_err(EINVAL
, "Unable to detect device type");
357 // First check for platform specific device types
358 dev
= get_custom_smart_device(name
, type
);
359 if (dev
|| get_errno())
362 if (!strcmp(type
, "ata"))
363 dev
= get_ata_device(name
, type
);
364 else if (!strcmp(type
, "scsi"))
365 dev
= get_scsi_device(name
, type
);
367 else if ( ((!strncmp(type
, "sat", 3) && (!type
[3] || strchr(",+", type
[3])))
368 || (!strncmp(type
, "usb", 3)))) {
369 // Split "sat...+base..." -> ("sat...", "base...")
370 unsigned satlen
= strcspn(type
, "+");
371 std::string
sattype(type
, satlen
);
372 const char * basetype
= (type
[satlen
] ? type
+satlen
+1 : "");
373 // Recurse to allocate base device, default is standard SCSI
376 smart_device_auto_ptr
basedev( get_smart_device(name
, basetype
) );
378 set_err(EINVAL
, "Type '%s+...': %s", sattype
.c_str(), get_errmsg());
381 // Result must be SCSI
382 if (!basedev
->is_scsi()) {
383 set_err(EINVAL
, "Type '%s+...': Device type '%s' is not SCSI", sattype
.c_str(), basetype
);
387 ata_device
* satdev
= get_sat_device(sattype
.c_str(), basedev
->to_scsi());
395 set_err(EINVAL
, "Unknown device type '%s'", type
);
398 if (!dev
&& !get_errno())
399 set_err(EINVAL
, "Not a device of type '%s'", type
);
403 smart_device
* smart_interface::get_custom_smart_device(const char * /*name*/, const char * /*type*/)
408 std::string
smart_interface::get_valid_custom_dev_types_str()