]> git.proxmox.com Git - mirror_smartmontools-debian.git/blame - dev_interface.cpp
Imported Upstream version 5.42+svn3561
[mirror_smartmontools-debian.git] / dev_interface.cpp
CommitLineData
2127e193
GI
1/*
2 * dev_interface.cpp
3 *
4 * Home page of code is: http://smartmontools.sourceforge.net
5 *
d008864d 6 * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
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
GI
20#include "dev_interface.h"
21#include "dev_tunnelled.h"
22#include "utility.h"
23
cfbba5b9
GI
24#include <errno.h>
25#include <stdarg.h>
2127e193
GI
26#include <stdexcept>
27
e165493d
GI
28#if defined(HAVE_GETTIMEOFDAY)
29#include <sys/time.h>
30#elif defined(HAVE_FTIME)
31#include <sys/timeb.h>
32#endif
33
f4e463df 34const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 3554 2012-06-01 20:11:46Z chrfranke $"
2127e193
GI
35 DEV_INTERFACE_H_CVSID;
36
37/////////////////////////////////////////////////////////////////////////////
38// smart_device
39
40smart_device::smart_device(smart_interface * intf, const char * dev_name,
41 const char * dev_type, const char * req_type)
42: m_intf(intf), m_info(dev_name, dev_type, req_type),
43 m_ata_ptr(0), m_scsi_ptr(0)
44{
45}
46
47smart_device::smart_device(do_not_use_in_implementation_classes)
48: m_intf(0), m_ata_ptr(0), m_scsi_ptr(0)
49{
50 throw std::logic_error("smart_device: wrong constructor called in implementation class");
51}
52
53smart_device::~smart_device() throw()
54{
55}
56
f4e463df
GI
57bool smart_device::is_syscall_unsup() const
58{
59 if (get_errno() == ENOSYS)
60 return true;
61#ifdef ENOTSUP
62 if (get_errno() == ENOTSUP)
63 return true;
64#endif
65 return false;
66}
67
2127e193
GI
68bool smart_device::set_err(int no, const char * msg, ...)
69{
70 if (!msg)
71 return set_err(no);
72 m_err.no = no;
73 va_list ap; va_start(ap, msg);
74 m_err.msg = vstrprintf(msg, ap);
75 va_end(ap);
76 return false;
77}
78
79bool smart_device::set_err(int no)
80{
d008864d 81 return smi()->set_err_var(&m_err, no);
2127e193
GI
82}
83
84smart_device * smart_device::autodetect_open()
85{
86 open();
87 return this;
88}
89
90bool smart_device::owns(const smart_device * /*dev*/) const
91{
92 return false;
93}
94
95void smart_device::release(const smart_device * /*dev*/)
96{
97}
98
99
100/////////////////////////////////////////////////////////////////////////////
101// ata_device
102
103ata_in_regs_48bit::ata_in_regs_48bit()
104: features_16(features, prev.features),
105 sector_count_16(sector_count, prev.sector_count),
106 lba_low_16(lba_low, prev.lba_low),
107 lba_mid_16(lba_mid, prev.lba_mid),
a23d5117
GI
108 lba_high_16(lba_high, prev.lba_high),
109 lba_48( lba_low, lba_mid, lba_high,
110 prev.lba_low, prev.lba_mid, prev.lba_high)
2127e193
GI
111{
112}
113
114ata_out_regs_48bit::ata_out_regs_48bit()
115: sector_count_16(sector_count, prev.sector_count),
116 lba_low_16(lba_low, prev.lba_low),
117 lba_mid_16(lba_mid, prev.lba_mid),
a23d5117
GI
118 lba_high_16(lba_high, prev.lba_high),
119 lba_48( lba_low, lba_mid, lba_high,
120 prev.lba_low, prev.lba_mid, prev.lba_high)
2127e193
GI
121{
122}
123
124ata_cmd_in::ata_cmd_in()
125: direction(no_data),
126 buffer(0),
127 size(0)
128{
129}
130
131ata_cmd_out::ata_cmd_out()
132{
133}
134
135bool ata_device::ata_pass_through(const ata_cmd_in & in)
136{
137 ata_cmd_out dummy;
138 return ata_pass_through(in, dummy);
139}
140
141bool ata_device::ata_cmd_is_ok(const ata_cmd_in & in,
142 bool data_out_support /*= false*/,
143 bool multi_sector_support /*= false*/,
144 bool ata_48bit_support /*= false*/)
145{
146 // Check DATA IN/OUT
147 switch (in.direction) {
148 case ata_cmd_in::no_data: break;
149 case ata_cmd_in::data_in: break;
150 case ata_cmd_in::data_out: break;
151 default:
152 return set_err(EINVAL, "Invalid data direction %d", (int)in.direction);
153 }
154
155 // Check buffer size
156 if (in.direction == ata_cmd_in::no_data) {
157 if (in.size)
158 return set_err(EINVAL, "Buffer size %u > 0 for NO DATA command", in.size);
159 }
160 else {
161 if (!in.buffer)
162 return set_err(EINVAL, "Buffer not set for DATA IN/OUT command");
163 unsigned count = (in.in_regs.prev.sector_count<<16)|in.in_regs.sector_count;
164 // TODO: Add check for sector count == 0
165 if (count * 512 != in.size)
166 return set_err(EINVAL, "Sector count %u does not match buffer size %u", count, in.size);
167 }
168
169 // Check features
170 if (in.direction == ata_cmd_in::data_out && !data_out_support)
171 return set_err(ENOSYS, "DATA OUT ATA commands not supported");
172 if (!(in.size == 0 || in.size == 512) && !multi_sector_support)
173 return set_err(ENOSYS, "Multi-sector ATA commands not supported");
174 if (in.in_regs.is_48bit_cmd() && !ata_48bit_support)
175 return set_err(ENOSYS, "48-bit ATA commands not supported");
176 return true;
177}
178
179bool ata_device::ata_identify_is_cached() const
180{
181 return false;
182}
183
184
185/////////////////////////////////////////////////////////////////////////////
186// tunnelled_device_base
187
188tunnelled_device_base::tunnelled_device_base(smart_device * tunnel_dev)
189: smart_device(never_called),
190 m_tunnel_base_dev(tunnel_dev)
191{
192}
193
194tunnelled_device_base::~tunnelled_device_base() throw()
195{
196 delete m_tunnel_base_dev;
197}
198
199bool tunnelled_device_base::is_open() const
200{
201 return (m_tunnel_base_dev && m_tunnel_base_dev->is_open());
202}
203
204bool tunnelled_device_base::open()
205{
206 if (!m_tunnel_base_dev)
207 return set_err(ENOSYS);
208 if (!m_tunnel_base_dev->open())
209 return set_err(m_tunnel_base_dev->get_err());
210 return true;
211}
212
213bool tunnelled_device_base::close()
214{
215 if (!m_tunnel_base_dev)
216 return true;
217 if (!m_tunnel_base_dev->close())
218 return set_err(m_tunnel_base_dev->get_err());
219 return true;
220}
221
222bool tunnelled_device_base::owns(const smart_device * dev) const
223{
224 return (m_tunnel_base_dev && (m_tunnel_base_dev == dev));
225}
226
227void tunnelled_device_base::release(const smart_device * dev)
228{
229 if (m_tunnel_base_dev == dev)
230 m_tunnel_base_dev = 0;
231}
232
233
234/////////////////////////////////////////////////////////////////////////////
235// smart_interface
236
237// Pointer to (usually singleton) interface object returned by ::smi()
238smart_interface * smart_interface::s_instance;
239
54965743 240std::string smart_interface::get_os_version_str()
2127e193
GI
241{
242 return SMARTMONTOOLS_BUILD_HOST;
243}
244
54965743 245std::string smart_interface::get_valid_dev_types_str()
2127e193 246{
2127e193 247 // default
54965743 248 std::string s =
d008864d 249 "ata, scsi, sat[,auto][,N][+TYPE], usbcypress[,X], usbjmicron[,x][,N], usbsunplus";
2127e193 250 // append custom
54965743
GI
251 std::string s2 = get_valid_custom_dev_types_str();
252 if (!s2.empty()) {
253 s += ", "; s += s2;
254 }
255 return s;
2127e193
GI
256}
257
54965743 258std::string smart_interface::get_app_examples(const char * /*appname*/)
2127e193 259{
54965743 260 return "";
2127e193
GI
261}
262
e165493d
GI
263int64_t smart_interface::get_timer_usec()
264{
265#if defined(HAVE_GETTIMEOFDAY)
266 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
267 {
268 static bool have_clock_monotonic = true;
269 if (have_clock_monotonic) {
270 struct timespec ts;
271 if (!clock_gettime(CLOCK_MONOTONIC, &ts))
272 return ts.tv_sec * 1000000LL + ts.tv_nsec/1000;
273 have_clock_monotonic = false;
274 }
275 }
276 #endif
277 {
278 struct timeval tv;
279 gettimeofday(&tv, 0);
280 return tv.tv_sec * 1000000LL + tv.tv_usec;
281 }
282#elif defined(HAVE_FTIME)
283 {
284 struct timeb tb;
285 ftime(&tb);
286 return tb.time * 1000000LL + tb.millitm * 1000;
287 }
288#else
289 return -1;
290#endif
291}
292
d008864d 293bool smart_interface::disable_system_auto_standby(bool /*disable*/)
2127e193 294{
d008864d
GI
295 return set_err(ENOSYS);
296}
297
298bool smart_interface::set_err(int no, const char * msg, ...)
299{
300 if (!msg)
301 return set_err(no);
2127e193
GI
302 m_err.no = no;
303 va_list ap; va_start(ap, msg);
304 m_err.msg = vstrprintf(msg, ap);
305 va_end(ap);
d008864d 306 return false;
2127e193
GI
307}
308
d008864d 309bool smart_interface::set_err(int no)
2127e193 310{
d008864d 311 return set_err_var(&m_err, no);
2127e193
GI
312}
313
d008864d 314bool smart_interface::set_err_var(smart_device::error_info * err, int no)
2127e193
GI
315{
316 err->no = no;
317 err->msg = get_msg_for_errno(no);
318 if (err->msg.empty() && no != 0)
319 err->msg = strprintf("Unknown error %d", no);
d008864d 320 return false;
2127e193
GI
321}
322
323const char * smart_interface::get_msg_for_errno(int no)
324{
325 return strerror(no);
326}
327
328
329/////////////////////////////////////////////////////////////////////////////
330// Default device factory
331
332smart_device * smart_interface::get_smart_device(const char * name, const char * type)
333{
334 clear_err();
cfbba5b9
GI
335
336 // Call platform specific autodetection if no device type specified
337 smart_device * dev;
2127e193 338 if (!type || !*type) {
cfbba5b9 339 dev = autodetect_smart_device(name);
2127e193
GI
340 if (!dev && !get_errno())
341 set_err(EINVAL, "Unable to detect device type");
342 return dev;
343 }
344
cfbba5b9
GI
345 // First check for platform specific device types
346 dev = get_custom_smart_device(name, type);
2127e193
GI
347 if (dev || get_errno())
348 return dev;
349
350 if (!strcmp(type, "ata"))
351 dev = get_ata_device(name, type);
352 else if (!strcmp(type, "scsi"))
353 dev = get_scsi_device(name, type);
354
355 else if ( ((!strncmp(type, "sat", 3) && (!type[3] || strchr(",+", type[3])))
356 || (!strncmp(type, "usb", 3)))) {
357 // Split "sat...+base..." -> ("sat...", "base...")
358 unsigned satlen = strcspn(type, "+");
359 std::string sattype(type, satlen);
360 const char * basetype = (type[satlen] ? type+satlen+1 : "");
361 // Recurse to allocate base device, default is standard SCSI
362 if (!*basetype)
363 basetype = "scsi";
bed94269
GI
364 smart_device_auto_ptr basedev( get_smart_device(name, basetype) );
365 if (!basedev) {
2127e193
GI
366 set_err(EINVAL, "Type '%s+...': %s", sattype.c_str(), get_errmsg());
367 return 0;
368 }
369 // Result must be SCSI
bed94269 370 if (!basedev->is_scsi()) {
2127e193
GI
371 set_err(EINVAL, "Type '%s+...': Device type '%s' is not SCSI", sattype.c_str(), basetype);
372 return 0;
373 }
374 // Attach SAT tunnel
bed94269
GI
375 ata_device * satdev = get_sat_device(sattype.c_str(), basedev->to_scsi());
376 if (!satdev)
377 return 0;
378 basedev.release();
379 return satdev;
2127e193
GI
380 }
381
382 else {
383 set_err(EINVAL, "Unknown device type '%s'", type);
384 return 0;
385 }
386 if (!dev && !get_errno())
387 set_err(EINVAL, "Not a device of type '%s'", type);
388 return dev;
389}
390
391smart_device * smart_interface::get_custom_smart_device(const char * /*name*/, const char * /*type*/)
392{
393 return 0;
394}
395
54965743 396std::string smart_interface::get_valid_custom_dev_types_str()
2127e193 397{
54965743 398 return "";
2127e193 399}