]> git.proxmox.com Git - mirror_smartmontools-debian.git/blame - dev_interface.cpp
New upstream version 6.6
[mirror_smartmontools-debian.git] / dev_interface.cpp
CommitLineData
2127e193
GI
1/*
2 * dev_interface.cpp
3 *
a86ec89e 4 * Home page of code is: http://www.smartmontools.org
2127e193 5 *
f9e10201 6 * Copyright (C) 2008-16 Christian Franke
2127e193
GI
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#include "config.h"
19#include "int64.h"
2127e193 20#include "dev_interface.h"
f9e10201 21#include "dev_intelliprop.h"
2127e193 22#include "dev_tunnelled.h"
ee38a438 23#include "atacmds.h" // ATA_SMART_CMD/STATUS
2127e193
GI
24#include "utility.h"
25
cfbba5b9
GI
26#include <errno.h>
27#include <stdarg.h>
2127e193
GI
28#include <stdexcept>
29
e165493d
GI
30#if defined(HAVE_GETTIMEOFDAY)
31#include <sys/time.h>
32#elif defined(HAVE_FTIME)
33#include <sys/timeb.h>
34#endif
35
f9e10201 36const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 4431 2017-08-08 19:38:15Z chrfranke $"
2127e193
GI
37 DEV_INTERFACE_H_CVSID;
38
39/////////////////////////////////////////////////////////////////////////////
40// smart_device
41
a86ec89e
GI
42int smart_device::s_num_objects = 0;
43
2127e193
GI
44smart_device::smart_device(smart_interface * intf, const char * dev_name,
45 const char * dev_type, const char * req_type)
46: m_intf(intf), m_info(dev_name, dev_type, req_type),
a86ec89e 47 m_ata_ptr(0), m_scsi_ptr(0), m_nvme_ptr(0)
2127e193 48{
a86ec89e 49 s_num_objects++;
2127e193
GI
50}
51
52smart_device::smart_device(do_not_use_in_implementation_classes)
a86ec89e 53: m_intf(0), m_ata_ptr(0), m_scsi_ptr(0), m_nvme_ptr(0)
2127e193
GI
54{
55 throw std::logic_error("smart_device: wrong constructor called in implementation class");
56}
57
58smart_device::~smart_device() throw()
59{
a86ec89e 60 s_num_objects--;
2127e193
GI
61}
62
f4e463df
GI
63bool smart_device::is_syscall_unsup() const
64{
65 if (get_errno() == ENOSYS)
66 return true;
67#ifdef ENOTSUP
68 if (get_errno() == ENOTSUP)
69 return true;
70#endif
71 return false;
72}
73
2127e193
GI
74bool smart_device::set_err(int no, const char * msg, ...)
75{
76 if (!msg)
77 return set_err(no);
78 m_err.no = no;
79 va_list ap; va_start(ap, msg);
80 m_err.msg = vstrprintf(msg, ap);
81 va_end(ap);
82 return false;
83}
84
85bool smart_device::set_err(int no)
86{
d008864d 87 return smi()->set_err_var(&m_err, no);
2127e193
GI
88}
89
90smart_device * smart_device::autodetect_open()
91{
92 open();
93 return this;
94}
95
a86ec89e
GI
96bool smart_device::is_powered_down()
97{
98 return false;
99}
100
2127e193
GI
101bool smart_device::owns(const smart_device * /*dev*/) const
102{
103 return false;
104}
105
106void smart_device::release(const smart_device * /*dev*/)
107{
108}
109
110
111/////////////////////////////////////////////////////////////////////////////
112// ata_device
113
114ata_in_regs_48bit::ata_in_regs_48bit()
115: features_16(features, prev.features),
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),
a23d5117
GI
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)
2127e193
GI
122{
123}
124
125ata_out_regs_48bit::ata_out_regs_48bit()
126: sector_count_16(sector_count, prev.sector_count),
127 lba_low_16(lba_low, prev.lba_low),
128 lba_mid_16(lba_mid, prev.lba_mid),
a23d5117
GI
129 lba_high_16(lba_high, prev.lba_high),
130 lba_48( lba_low, lba_mid, lba_high,
131 prev.lba_low, prev.lba_mid, prev.lba_high)
2127e193
GI
132{
133}
134
135ata_cmd_in::ata_cmd_in()
136: direction(no_data),
137 buffer(0),
138 size(0)
139{
140}
141
142ata_cmd_out::ata_cmd_out()
143{
144}
145
146bool ata_device::ata_pass_through(const ata_cmd_in & in)
147{
148 ata_cmd_out dummy;
149 return ata_pass_through(in, dummy);
150}
151
ee38a438
GI
152bool ata_device::ata_cmd_is_supported(const ata_cmd_in & in,
153 unsigned flags, const char * type /* = 0 */)
2127e193
GI
154{
155 // Check DATA IN/OUT
156 switch (in.direction) {
157 case ata_cmd_in::no_data: break;
158 case ata_cmd_in::data_in: break;
159 case ata_cmd_in::data_out: break;
160 default:
161 return set_err(EINVAL, "Invalid data direction %d", (int)in.direction);
162 }
163
164 // Check buffer size
165 if (in.direction == ata_cmd_in::no_data) {
166 if (in.size)
167 return set_err(EINVAL, "Buffer size %u > 0 for NO DATA command", in.size);
168 }
169 else {
170 if (!in.buffer)
171 return set_err(EINVAL, "Buffer not set for DATA IN/OUT command");
172 unsigned count = (in.in_regs.prev.sector_count<<16)|in.in_regs.sector_count;
173 // TODO: Add check for sector count == 0
174 if (count * 512 != in.size)
175 return set_err(EINVAL, "Sector count %u does not match buffer size %u", count, in.size);
176 }
177
178 // Check features
ee38a438
GI
179 const char * errmsg = 0;
180 if (in.direction == ata_cmd_in::data_out && !(flags & supports_data_out))
181 errmsg = "DATA OUT ATA commands not implemented";
182 else if ( in.out_needed.is_set() && !(flags & supports_output_regs)
183 && !( in.in_regs.command == ATA_SMART_CMD
184 && in.in_regs.features == ATA_SMART_STATUS
185 && (flags & supports_smart_status)))
186 errmsg = "Read of ATA output registers not implemented";
187 else if (!(in.size == 0 || in.size == 512) && !(flags & supports_multi_sector))
188 errmsg = "Multi-sector ATA commands not implemented";
189 else if (in.in_regs.is_48bit_cmd() && !(flags & (supports_48bit_hi_null|supports_48bit)))
190 errmsg = "48-bit ATA commands not implemented";
191 else if (in.in_regs.is_real_48bit_cmd() && !(flags & supports_48bit))
192 errmsg = "48-bit ATA commands not fully implemented";
193
194 if (errmsg)
195 return set_err(ENOSYS, "%s%s%s%s", errmsg,
196 (type ? " [" : ""), (type ? type : ""), (type ? "]" : ""));
197
2127e193
GI
198 return true;
199}
200
201bool ata_device::ata_identify_is_cached() const
202{
203 return false;
204}
205
206
a86ec89e
GI
207/////////////////////////////////////////////////////////////////////////////
208// nvme_device
209
210bool nvme_device::set_nvme_err(nvme_cmd_out & out, unsigned status, const char * msg /* = 0 */)
211{
212 if (!status)
213 throw std::logic_error("nvme_device: set_nvme_err() called with status=0");
214
215 out.status = status;
216 out.status_valid = true;
217 return set_err(EIO, "%sNVMe Status 0x%02x", (msg ? msg : ""), status);
218}
219
220
2127e193
GI
221/////////////////////////////////////////////////////////////////////////////
222// tunnelled_device_base
223
224tunnelled_device_base::tunnelled_device_base(smart_device * tunnel_dev)
225: smart_device(never_called),
226 m_tunnel_base_dev(tunnel_dev)
227{
228}
229
230tunnelled_device_base::~tunnelled_device_base() throw()
231{
232 delete m_tunnel_base_dev;
233}
234
235bool tunnelled_device_base::is_open() const
236{
237 return (m_tunnel_base_dev && m_tunnel_base_dev->is_open());
238}
239
240bool tunnelled_device_base::open()
241{
242 if (!m_tunnel_base_dev)
243 return set_err(ENOSYS);
244 if (!m_tunnel_base_dev->open())
245 return set_err(m_tunnel_base_dev->get_err());
246 return true;
247}
248
249bool tunnelled_device_base::close()
250{
251 if (!m_tunnel_base_dev)
252 return true;
253 if (!m_tunnel_base_dev->close())
254 return set_err(m_tunnel_base_dev->get_err());
255 return true;
256}
257
258bool tunnelled_device_base::owns(const smart_device * dev) const
259{
260 return (m_tunnel_base_dev && (m_tunnel_base_dev == dev));
261}
262
263void tunnelled_device_base::release(const smart_device * dev)
264{
265 if (m_tunnel_base_dev == dev)
266 m_tunnel_base_dev = 0;
267}
268
269
270/////////////////////////////////////////////////////////////////////////////
271// smart_interface
272
273// Pointer to (usually singleton) interface object returned by ::smi()
274smart_interface * smart_interface::s_instance;
275
54965743 276std::string smart_interface::get_os_version_str()
2127e193
GI
277{
278 return SMARTMONTOOLS_BUILD_HOST;
279}
280
54965743 281std::string smart_interface::get_valid_dev_types_str()
2127e193 282{
2127e193 283 // default
54965743 284 std::string s =
f9e10201
JD
285 "ata, scsi, nvme[,NSID], sat[,auto][,N][+TYPE], usbcypress[,X], "
286 "usbjmicron[,p][,x][,N], usbprolific, usbsunplus, intelliprop,N[+TYPE]";
2127e193 287 // append custom
54965743
GI
288 std::string s2 = get_valid_custom_dev_types_str();
289 if (!s2.empty()) {
290 s += ", "; s += s2;
291 }
292 return s;
2127e193
GI
293}
294
54965743 295std::string smart_interface::get_app_examples(const char * /*appname*/)
2127e193 296{
54965743 297 return "";
2127e193
GI
298}
299
e165493d
GI
300int64_t smart_interface::get_timer_usec()
301{
302#if defined(HAVE_GETTIMEOFDAY)
303 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
304 {
305 static bool have_clock_monotonic = true;
306 if (have_clock_monotonic) {
307 struct timespec ts;
308 if (!clock_gettime(CLOCK_MONOTONIC, &ts))
309 return ts.tv_sec * 1000000LL + ts.tv_nsec/1000;
310 have_clock_monotonic = false;
311 }
312 }
313 #endif
314 {
315 struct timeval tv;
316 gettimeofday(&tv, 0);
317 return tv.tv_sec * 1000000LL + tv.tv_usec;
318 }
319#elif defined(HAVE_FTIME)
320 {
321 struct timeb tb;
322 ftime(&tb);
323 return tb.time * 1000000LL + tb.millitm * 1000;
324 }
325#else
326 return -1;
327#endif
328}
329
d008864d 330bool smart_interface::disable_system_auto_standby(bool /*disable*/)
2127e193 331{
d008864d
GI
332 return set_err(ENOSYS);
333}
334
335bool smart_interface::set_err(int no, const char * msg, ...)
336{
337 if (!msg)
338 return set_err(no);
2127e193
GI
339 m_err.no = no;
340 va_list ap; va_start(ap, msg);
341 m_err.msg = vstrprintf(msg, ap);
342 va_end(ap);
d008864d 343 return false;
2127e193
GI
344}
345
d008864d 346bool smart_interface::set_err(int no)
2127e193 347{
d008864d 348 return set_err_var(&m_err, no);
2127e193
GI
349}
350
d008864d 351bool smart_interface::set_err_var(smart_device::error_info * err, int no)
2127e193
GI
352{
353 err->no = no;
354 err->msg = get_msg_for_errno(no);
355 if (err->msg.empty() && no != 0)
356 err->msg = strprintf("Unknown error %d", no);
d008864d 357 return false;
2127e193
GI
358}
359
360const char * smart_interface::get_msg_for_errno(int no)
361{
362 return strerror(no);
363}
364
365
366/////////////////////////////////////////////////////////////////////////////
367// Default device factory
368
369smart_device * smart_interface::get_smart_device(const char * name, const char * type)
370{
371 clear_err();
cfbba5b9
GI
372
373 // Call platform specific autodetection if no device type specified
374 smart_device * dev;
2127e193 375 if (!type || !*type) {
cfbba5b9 376 dev = autodetect_smart_device(name);
2127e193
GI
377 if (!dev && !get_errno())
378 set_err(EINVAL, "Unable to detect device type");
379 return dev;
380 }
381
cfbba5b9
GI
382 // First check for platform specific device types
383 dev = get_custom_smart_device(name, type);
2127e193
GI
384 if (dev || get_errno())
385 return dev;
386
387 if (!strcmp(type, "ata"))
388 dev = get_ata_device(name, type);
389 else if (!strcmp(type, "scsi"))
390 dev = get_scsi_device(name, type);
391
a86ec89e
GI
392 else if (str_starts_with(type, "nvme")) {
393 int n1 = -1, n2 = -1, len = strlen(type);
394 unsigned nsid = 0; // invalid namespace id -> use default
395 sscanf(type, "nvme%n,0x%x%n", &n1, &nsid, &n2);
396 if (!(n1 == len || n2 == len)) {
397 set_err(EINVAL, "Invalid NVMe namespace id in '%s'", type);
398 return 0;
399 }
400 dev = get_nvme_device(name, type, nsid);
401 }
402
2127e193
GI
403 else if ( ((!strncmp(type, "sat", 3) && (!type[3] || strchr(",+", type[3])))
404 || (!strncmp(type, "usb", 3)))) {
405 // Split "sat...+base..." -> ("sat...", "base...")
406 unsigned satlen = strcspn(type, "+");
407 std::string sattype(type, satlen);
408 const char * basetype = (type[satlen] ? type+satlen+1 : "");
409 // Recurse to allocate base device, default is standard SCSI
410 if (!*basetype)
411 basetype = "scsi";
bed94269
GI
412 smart_device_auto_ptr basedev( get_smart_device(name, basetype) );
413 if (!basedev) {
2127e193
GI
414 set_err(EINVAL, "Type '%s+...': %s", sattype.c_str(), get_errmsg());
415 return 0;
416 }
417 // Result must be SCSI
bed94269 418 if (!basedev->is_scsi()) {
2127e193
GI
419 set_err(EINVAL, "Type '%s+...': Device type '%s' is not SCSI", sattype.c_str(), basetype);
420 return 0;
421 }
422 // Attach SAT tunnel
a86ec89e 423 return get_sat_device(sattype.c_str(), basedev.release()->to_scsi());
2127e193
GI
424 }
425
f9e10201
JD
426 else if (str_starts_with(type, "intelliprop")) {
427 // Parse "intelliprop,N[+base...]"
428 unsigned phydrive = ~0; int n = -1; char c = 0;
429 sscanf(type, "intelliprop,%u%n%c", &phydrive, &n, &c);
430 if (!((n == (int)strlen(type) || c == '+') && phydrive <= 3)) {
431 set_err(EINVAL, "Option '-d intelliprop,N' requires N between 0 and 3");
432 return 0;
433 }
434 const char * basetype = (type[n] ? type + n + 1 : "");
435 // Recurse to allocate base device, default is standard ATA
436 if (!*basetype)
437 basetype = "ata";
438 smart_device_auto_ptr basedev( get_smart_device(name, basetype) );
439 if (!basedev) {
440 set_err(EINVAL, "Type '%s': %s", type, get_errmsg());
441 return 0;
442 }
443 // Result must be ATA
444 if (!basedev->is_ata()) {
445 set_err(EINVAL, "Type '%s': Device type '%s' is not ATA", type, basetype);
446 return 0;
447 }
448 return get_intelliprop_device(this, phydrive, basedev.release()->to_ata());
449 }
450
2127e193
GI
451 else {
452 set_err(EINVAL, "Unknown device type '%s'", type);
453 return 0;
454 }
455 if (!dev && !get_errno())
456 set_err(EINVAL, "Not a device of type '%s'", type);
457 return dev;
458}
459
a86ec89e
GI
460bool smart_interface::scan_smart_devices(smart_device_list & devlist,
461 const smart_devtype_list & types, const char * pattern /* = 0 */)
462{
463 unsigned n = types.size();
464 if (n == 0)
465 return scan_smart_devices(devlist, (const char *)0, pattern);
466 if (n == 1)
467 return scan_smart_devices(devlist, types.front().c_str(), pattern);
468
469 for (unsigned i = 0; i < n; i++) {
470 smart_device_list tmplist;
471 if (!scan_smart_devices(tmplist, types[i].c_str(), pattern))
472 return false;
473 devlist.append(tmplist);
474 }
475
476 return true;
477}
478
479nvme_device * smart_interface::get_nvme_device(const char * /*name*/, const char * /*type*/, unsigned /*nsid*/)
480{
481 set_err(ENOSYS, "NVMe devices are not supported in this version of smartmontools");
482 return 0;
483}
484
2127e193
GI
485smart_device * smart_interface::get_custom_smart_device(const char * /*name*/, const char * /*type*/)
486{
487 return 0;
488}
489
54965743 490std::string smart_interface::get_valid_custom_dev_types_str()
2127e193 491{
54965743 492 return "";
2127e193 493}