4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2006-12 Douglas Gilbert <dgilbert@interlog.com>
7 * Copyright (C) 2009-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
14 * You should have received a copy of the GNU General Public License
15 * (for example COPYING); if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * The code in this file is based on the SCSI to ATA Translation (SAT)
19 * draft found at http://www.t10.org . The original draft used for this
20 * code is sat-r08.pdf which is not too far away from becoming a
21 * standard. The SAT commands of interest to smartmontools are the
22 * ATA PASS THROUGH SCSI (16) and ATA PASS THROUGH SCSI (12) defined in
23 * section 12 of that document.
25 * sat-r09.pdf is the most recent, easily accessible draft prior to the
26 * original SAT standard (ANSI INCITS 431-2007). By mid-2009 the second
27 * version of the SAT standard (SAT-2) is nearing standardization. In
28 * their wisdom an incompatible change has been introduced in draft
29 * sat2r08a.pdf in the area of the ATA RETURN DESCRIPTOR. A new "fixed
30 * format" ATA RETURN buffer has been defined (sat2r08b.pdf section
31 * 12.2.7) for the case when DSENSE=0 in the Control mode page.
32 * Unfortunately this is the normal case. If the change stands our
33 * code will need to be extended for this case.
35 * With more transports "hiding" SATA disks (and other S-ATAPI devices)
36 * behind a SCSI command set, accessing special features like SMART
37 * information becomes a challenge. The SAT standard offers ATA PASS
38 * THROUGH commands for special usages. Note that the SAT layer may
39 * be inside a generic OS layer (e.g. libata in linux), in a host
40 * adapter (HA or HBA) firmware, or somewhere on the interconnect
41 * between the host computer and the SATA devices (e.g. a RAID made
42 * of SATA disks and the RAID talks "SCSI" to the host computer).
43 * Note that in the latter case, this code does not solve the
44 * addressing issue (i.e. which SATA disk to address behind the logical
45 * SCSI (RAID) interface).
58 #include "atacmds.h" // ataReadHDIdentity()
59 #include "knowndrives.h" // lookup_usb_device()
61 #include "dev_interface.h"
62 #include "dev_ata_cmd_set.h" // ata_device_with_command_set
63 #include "dev_tunnelled.h" // tunnelled_device<>
65 const char * scsiata_cpp_cvsid
= "$Id: scsiata.cpp 3922 2014-06-23 19:17:18Z chrfranke $";
67 /* This is a slightly stretched SCSI sense "descriptor" format header.
68 The addition is to allow the 0x70 and 0x71 response codes. The idea
69 is to place the salient data of both "fixed" and "descriptor" sense
70 format into one structure to ease application processing.
71 The original sense buffer should be kept around for those cases
72 in which more information is required (e.g. the LBA of a MEDIUM ERROR). */
73 /// Abridged SCSI sense data
74 struct sg_scsi_sense_hdr
{
75 unsigned char response_code
; /* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */
76 unsigned char sense_key
;
82 unsigned char additional_length
;
85 /* Maps the salient data from a sense buffer which is in either fixed or
86 descriptor format into a structure mimicking a descriptor format
87 header (i.e. the first 8 bytes of sense descriptor format).
88 If zero response code returns 0. Otherwise returns 1 and if 'sshp' is
89 non-NULL then zero all fields and then set the appropriate fields in
90 that structure. sshp::additional_length is always 0 for response
91 codes 0x70 and 0x71 (fixed format). */
92 static int sg_scsi_normalize_sense(const unsigned char * sensep
, int sb_len
,
93 struct sg_scsi_sense_hdr
* sshp
);
95 #define SAT_ATA_PASSTHROUGH_12LEN 12
96 #define SAT_ATA_PASSTHROUGH_16LEN 16
98 #define DEF_SAT_ATA_PASSTHRU_SIZE 16
99 #define ATA_RETURN_DESCRIPTOR 9
102 namespace sat
{ // no need to publish anything, name provided for Doxygen
105 /// Implements ATA by tunnelling through SCSI.
108 : public tunnelled_device
<
109 /*implements*/ ata_device
110 /*by tunnelling through a*/, scsi_device
112 virtual public /*implements*/ scsi_device
115 sat_device(smart_interface
* intf
, scsi_device
* scsidev
,
116 const char * req_type
, int passthrulen
= 0, bool enable_auto
= false);
118 virtual ~sat_device() throw();
120 virtual smart_device
* autodetect_open();
122 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
124 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
132 sat_device::sat_device(smart_interface
* intf
, scsi_device
* scsidev
,
133 const char * req_type
, int passthrulen
/* = 0 */, bool enable_auto
/* = false */)
134 : smart_device(intf
, scsidev
->get_dev_name(),
135 (enable_auto
? "sat,auto" : "sat"), req_type
),
136 tunnelled_device
<ata_device
, scsi_device
>(scsidev
),
137 m_passthrulen(passthrulen
),
138 m_enable_auto(enable_auto
)
141 hide_ata(); // Start as SCSI, switch to ATA in autodetect_open()
143 hide_scsi(); // ATA always
144 if (strcmp(scsidev
->get_dev_type(), "scsi"))
145 set_info().dev_type
+= strprintf("+%s", scsidev
->get_dev_type());
147 set_info().info_name
= strprintf("%s [%sSAT]", scsidev
->get_info_name(),
148 (enable_auto
? "SCSI/" : ""));
151 sat_device::~sat_device() throw()
156 // cdb[0]: ATA PASS THROUGH (16) SCSI command opcode byte (0x85)
157 // cdb[1]: multiple_count, protocol + extend
158 // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
159 // cdb[3]: features (15:8)
160 // cdb[4]: features (7:0)
161 // cdb[5]: sector_count (15:8)
162 // cdb[6]: sector_count (7:0)
163 // cdb[7]: lba_low (15:8)
164 // cdb[8]: lba_low (7:0)
165 // cdb[9]: lba_mid (15:8)
166 // cdb[10]: lba_mid (7:0)
167 // cdb[11]: lba_high (15:8)
168 // cdb[12]: lba_high (7:0)
170 // cdb[14]: (ata) command
171 // cdb[15]: control (SCSI, leave as zero)
173 // 24 bit lba (from MSB): cdb[12] cdb[10] cdb[8]
174 // 48 bit lba (from MSB): cdb[11] cdb[9] cdb[7] cdb[12] cdb[10] cdb[8]
177 // cdb[0]: ATA PASS THROUGH (12) SCSI command opcode byte (0xa1)
178 // cdb[1]: multiple_count, protocol + extend
179 // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
180 // cdb[3]: features (7:0)
181 // cdb[4]: sector_count (7:0)
182 // cdb[5]: lba_low (7:0)
183 // cdb[6]: lba_mid (7:0)
184 // cdb[7]: lba_high (7:0)
186 // cdb[9]: (ata) command
188 // cdb[11]: control (SCSI, leave as zero)
191 // ATA Return Descriptor (component of descriptor sense data)
192 // des[0]: descriptor code (0x9)
193 // des[1]: additional descriptor length (0xc)
194 // des[2]: extend (bit 0)
196 // des[4]: sector_count (15:8)
197 // des[5]: sector_count (7:0)
198 // des[6]: lba_low (15:8)
199 // des[7]: lba_low (7:0)
200 // des[8]: lba_mid (15:8)
201 // des[9]: lba_mid (7:0)
202 // des[10]: lba_high (15:8)
203 // des[11]: lba_high (7:0)
210 // This interface routine takes ATA SMART commands and packages
211 // them in the SAT-defined ATA PASS THROUGH SCSI commands. There are
212 // two available SCSI commands: a 12 byte and 16 byte variant; the
213 // one used is chosen via this->m_passthrulen .
214 // DETAILED DESCRIPTION OF ARGUMENTS
215 // device: is the file descriptor provided by (a SCSI dvice type) open()
216 // command: defines the different ATA operations.
217 // select: additional input data if needed (which log, which type of
219 // data: location to write output data, if needed (512 bytes).
220 // Note: not all commands use all arguments.
222 // -1 if the command failed
223 // 0 if the command succeeded,
224 // STATUS_CHECK routine:
225 // -1 if the command failed
226 // 0 if the command succeeded and disk SMART status is "OK"
227 // 1 if the command succeeded and disk SMART status is "FAILING"
229 bool sat_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
231 if (!ata_cmd_is_supported(in
,
232 ata_device::supports_data_out
|
233 ata_device::supports_output_regs
|
234 ata_device::supports_multi_sector
|
235 ata_device::supports_48bit
,
240 struct scsi_cmnd_io io_hdr
;
241 struct scsi_sense_disect sinfo
;
242 struct sg_scsi_sense_hdr ssh
;
243 unsigned char cdb
[SAT_ATA_PASSTHROUGH_16LEN
];
244 unsigned char sense
[32];
245 const unsigned char * ardp
;
246 int status
, ard_len
, have_sense
;
248 int ck_cond
= 0; /* set to 1 to read register(s) back */
249 int protocol
= 3; /* non-data */
250 int t_dir
= 1; /* 0 -> to device, 1 -> from device */
251 int byte_block
= 1; /* 0 -> bytes, 1 -> 512 byte blocks */
252 int t_length
= 0; /* 0 -> no data transferred */
253 int passthru_size
= DEF_SAT_ATA_PASSTHRU_SIZE
;
255 memset(cdb
, 0, sizeof(cdb
));
256 memset(sense
, 0, sizeof(sense
));
258 // Set data direction
259 // TODO: This works only for commands where sector_count holds count!
260 switch (in
.direction
) {
261 case ata_cmd_in::no_data
:
263 case ata_cmd_in::data_in
:
264 protocol
= 4; // PIO data-in
265 t_length
= 2; // sector_count holds count
267 case ata_cmd_in::data_out
:
268 protocol
= 5; // PIO data-out
269 t_length
= 2; // sector_count holds count
270 t_dir
= 0; // to device
273 return set_err(EINVAL
, "sat_device::ata_pass_through: invalid direction=%d",
277 // Check condition if any output register needed
278 if (in
.out_needed
.is_set())
281 if ((SAT_ATA_PASSTHROUGH_12LEN
== m_passthrulen
) ||
282 (SAT_ATA_PASSTHROUGH_16LEN
== m_passthrulen
))
283 passthru_size
= m_passthrulen
;
285 // Set extend bit on 48-bit ATA command
286 if (in
.in_regs
.is_48bit_cmd()) {
287 if (passthru_size
!= SAT_ATA_PASSTHROUGH_16LEN
)
288 return set_err(ENOSYS
, "48-bit ATA commands require SAT ATA PASS-THROUGH (16)");
292 cdb
[0] = (SAT_ATA_PASSTHROUGH_12LEN
== passthru_size
) ?
293 SAT_ATA_PASSTHROUGH_12
: SAT_ATA_PASSTHROUGH_16
;
295 cdb
[1] = (protocol
<< 1) | extend
;
296 cdb
[2] = (ck_cond
<< 5) | (t_dir
<< 3) |
297 (byte_block
<< 2) | t_length
;
299 if (passthru_size
== SAT_ATA_PASSTHROUGH_12LEN
) {
300 // ATA PASS-THROUGH (12)
301 const ata_in_regs
& lo
= in
.in_regs
;
302 cdb
[3] = lo
.features
;
303 cdb
[4] = lo
.sector_count
;
306 cdb
[7] = lo
.lba_high
;
311 // ATA PASS-THROUGH (16)
312 const ata_in_regs
& lo
= in
.in_regs
;
313 const ata_in_regs
& hi
= in
.in_regs
.prev
;
314 // Note: all 'in.in_regs.prev.*' are always zero for 28-bit commands
315 cdb
[ 3] = hi
.features
;
316 cdb
[ 4] = lo
.features
;
317 cdb
[ 5] = hi
.sector_count
;
318 cdb
[ 6] = lo
.sector_count
;
319 cdb
[ 7] = hi
.lba_low
;
320 cdb
[ 8] = lo
.lba_low
;
321 cdb
[ 9] = hi
.lba_mid
;
322 cdb
[10] = lo
.lba_mid
;
323 cdb
[11] = hi
.lba_high
;
324 cdb
[12] = lo
.lba_high
;
326 cdb
[14] = lo
.command
;
329 memset(&io_hdr
, 0, sizeof(io_hdr
));
331 io_hdr
.dxfer_dir
= DXFER_NONE
;
332 io_hdr
.dxfer_len
= 0;
333 } else if (t_dir
) { /* from device */
334 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
335 io_hdr
.dxfer_len
= in
.size
;
336 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
337 memset(in
.buffer
, 0, in
.size
); // prefill with zeroes
338 } else { /* to device */
339 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
340 io_hdr
.dxfer_len
= in
.size
;
341 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
344 io_hdr
.cmnd_len
= passthru_size
;
345 io_hdr
.sensep
= sense
;
346 io_hdr
.max_sense_len
= sizeof(sense
);
347 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
349 scsi_device
* scsidev
= get_tunnel_dev();
350 if (!scsidev
->scsi_pass_through(&io_hdr
)) {
351 if (scsi_debugmode
> 0)
352 pout("sat_device::ata_pass_through: scsi_pass_through() failed, "
353 "errno=%d [%s]\n", scsidev
->get_errno(), scsidev
->get_errmsg());
354 return set_err(scsidev
->get_err());
358 have_sense
= sg_scsi_normalize_sense(io_hdr
.sensep
, io_hdr
.resp_sense_len
,
361 /* look for SAT ATA Return Descriptor */
362 ardp
= sg_scsi_sense_desc_find(io_hdr
.sensep
,
363 io_hdr
.resp_sense_len
,
364 ATA_RETURN_DESCRIPTOR
);
366 ard_len
= ardp
[1] + 2;
369 else if (ard_len
> 14)
372 scsi_do_sense_disect(&io_hdr
, &sinfo
);
373 status
= scsiSimpleSenseFilter(&sinfo
);
375 if (scsi_debugmode
> 0) {
376 pout("sat_device::ata_pass_through: scsi error: %s\n",
377 scsiErrString(status
));
378 if (ardp
&& (scsi_debugmode
> 1)) {
379 pout("Values from ATA Return Descriptor are:\n");
380 dStrHex((const char *)ardp
, ard_len
, 1);
383 if (t_dir
&& (t_length
> 0) && (in
.direction
== ata_cmd_in::data_in
))
384 memset(in
.buffer
, 0, in
.size
);
385 return set_err(EIO
, "scsi error %s", scsiErrString(status
));
388 if (ck_cond
) { /* expecting SAT specific sense data */
391 if (scsi_debugmode
> 1) {
392 pout("Values from ATA Return Descriptor are:\n");
393 dStrHex((const char *)ardp
, ard_len
, 1);
395 // Set output registers
396 ata_out_regs
& lo
= out
.out_regs
;
398 lo
.sector_count
= ardp
[ 5];
399 lo
.lba_low
= ardp
[ 7];
400 lo
.lba_mid
= ardp
[ 9];
401 lo
.lba_high
= ardp
[11];
402 lo
.device
= ardp
[12];
403 lo
.status
= ardp
[13];
404 if (in
.in_regs
.is_48bit_cmd()) {
405 ata_out_regs
& hi
= out
.out_regs
.prev
;
406 hi
.sector_count
= ardp
[ 4];
407 hi
.lba_low
= ardp
[ 6];
408 hi
.lba_mid
= ardp
[ 8];
409 hi
.lba_high
= ardp
[10];
414 ck_cond
= 0; /* not the type of sense data expected */
418 if ((ssh
.response_code
>= 0x72) &&
419 ((SCSI_SK_NO_SENSE
== ssh
.sense_key
) ||
420 (SCSI_SK_RECOVERED_ERR
== ssh
.sense_key
)) &&
422 (SCSI_ASCQ_ATA_PASS_THROUGH
== ssh
.ascq
)) {
424 if (scsi_debugmode
> 0) {
425 pout("Values from ATA Return Descriptor are:\n");
426 dStrHex((const char *)ardp
, ard_len
, 1);
428 return set_err(EIO
, "SAT command failed");
436 bool sat_device::scsi_pass_through(scsi_cmnd_io
* iop
)
438 scsi_device
* scsidev
= get_tunnel_dev();
439 if (!scsidev
->scsi_pass_through(iop
)) {
440 set_err(scsidev
->get_err());
446 smart_device
* sat_device::autodetect_open()
448 if (!open() || !m_enable_auto
)
451 scsi_device
* scsidev
= get_tunnel_dev();
453 unsigned char inqdata
[36] = {0, };
454 if (scsiStdInquiry(scsidev
, inqdata
, sizeof(inqdata
))) {
455 smart_device::error_info err
= scsidev
->get_err();
457 set_err(err
.no
, "INQUIRY [SAT]: %s", err
.msg
.c_str());
461 // Check for SAT "VENDOR"
462 int inqsize
= inqdata
[4] + 5;
463 bool sat
= (inqsize
>= 36 && !memcmp(inqdata
+ 8, "ATA ", 8));
469 set_info().dev_type
= (sat
? "sat" : scsidev
->get_dev_type());
470 set_info().info_name
= strprintf("%s [%s]", scsidev
->get_info_name(),
471 (sat
? "SAT" : "SCSI"));
477 /////////////////////////////////////////////////////////////////////////////
479 /* Attempt an IDENTIFY DEVICE ATA command via SATL when packet_interface
480 is false otherwise attempt IDENTIFY PACKET DEVICE. If successful
481 return true, else false */
483 static bool has_sat_pass_through(ata_device
* dev
, bool packet_interface
= false)
485 /* Note: malloc() ensures the read buffer lands on a single
486 page. This avoids some bugs seen on LSI controlers under
488 char *data
= (char *)malloc(512);
490 in
.in_regs
.command
= (packet_interface
? ATA_IDENTIFY_PACKET_DEVICE
: ATA_IDENTIFY_DEVICE
);
491 in
.set_data_in(data
, 1);
492 bool ret
= dev
->ata_pass_through(in
);
497 /////////////////////////////////////////////////////////////////////////////
499 /* Next two functions are borrowed from sg_lib.c in the sg3_utils
500 package. Same copyrght owner, same license as this file. */
501 static int sg_scsi_normalize_sense(const unsigned char * sensep
, int sb_len
,
502 struct sg_scsi_sense_hdr
* sshp
)
505 memset(sshp
, 0, sizeof(struct sg_scsi_sense_hdr
));
506 if ((NULL
== sensep
) || (0 == sb_len
) || (0x70 != (0x70 & sensep
[0])))
509 sshp
->response_code
= (0x7f & sensep
[0]);
510 if (sshp
->response_code
>= 0x72) { /* descriptor format */
512 sshp
->sense_key
= (0xf & sensep
[1]);
514 sshp
->asc
= sensep
[2];
516 sshp
->ascq
= sensep
[3];
518 sshp
->additional_length
= sensep
[7];
519 } else { /* fixed format */
521 sshp
->sense_key
= (0xf & sensep
[2]);
523 sb_len
= (sb_len
< (sensep
[7] + 8)) ? sb_len
:
526 sshp
->asc
= sensep
[12];
528 sshp
->ascq
= sensep
[13];
536 // Call scsi_pass_through and check sense.
537 // TODO: Provide as member function of class scsi_device (?)
538 static bool scsi_pass_through_and_check(scsi_device
* scsidev
, scsi_cmnd_io
* iop
,
539 const char * msg
= "")
541 // Provide sense buffer
542 unsigned char sense
[32] = {0, };
544 iop
->max_sense_len
= sizeof(sense
);
545 iop
->timeout
= SCSI_TIMEOUT_DEFAULT
;
548 if (!scsidev
->scsi_pass_through(iop
)) {
549 if (scsi_debugmode
> 0)
550 pout("%sscsi_pass_through() failed, errno=%d [%s]\n",
551 msg
, scsidev
->get_errno(), scsidev
->get_errmsg());
556 scsi_sense_disect sinfo
;
557 scsi_do_sense_disect(iop
, &sinfo
);
558 int err
= scsiSimpleSenseFilter(&sinfo
);
560 if (scsi_debugmode
> 0)
561 pout("%sscsi error: %s\n", msg
, scsiErrString(err
));
562 return scsidev
->set_err(EIO
, "scsi error %s", scsiErrString(err
));
569 /////////////////////////////////////////////////////////////////////////////
573 /// Cypress USB Brigde support.
575 class usbcypress_device
576 : public tunnelled_device
<
577 /*implements*/ ata_device_with_command_set
578 /*by tunnelling through a*/, scsi_device
582 usbcypress_device(smart_interface
* intf
, scsi_device
* scsidev
,
583 const char * req_type
, unsigned char signature
);
585 virtual ~usbcypress_device() throw();
588 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
590 unsigned char m_signature
;
594 usbcypress_device::usbcypress_device(smart_interface
* intf
, scsi_device
* scsidev
,
595 const char * req_type
, unsigned char signature
)
596 : smart_device(intf
, scsidev
->get_dev_name(), "sat", req_type
),
597 tunnelled_device
<ata_device_with_command_set
, scsi_device
>(scsidev
),
598 m_signature(signature
)
600 set_info().info_name
= strprintf("%s [USB Cypress]", scsidev
->get_info_name());
603 usbcypress_device::~usbcypress_device() throw()
608 /* see cy7c68300c_8.pdf for more information */
609 #define USBCYPRESS_PASSTHROUGH_LEN 16
610 int usbcypress_device::ata_command_interface(smart_command_set command
, int select
, char *data
)
612 struct scsi_cmnd_io io_hdr
;
613 unsigned char cdb
[USBCYPRESS_PASSTHROUGH_LEN
];
614 unsigned char sense
[32];
617 int ck_cond
= 0; /* set to 1 to read register(s) back */
618 int t_dir
= 1; /* 0 -> to device, 1 -> from device */
619 int byte_block
= 1; /* 0 -> bytes, 1 -> 512 byte blocks */
620 int t_length
= 0; /* 0 -> no data transferred */
623 int sector_count
= 0;
627 int passthru_size
= USBCYPRESS_PASSTHROUGH_LEN
;
629 memset(cdb
, 0, sizeof(cdb
));
630 memset(sense
, 0, sizeof(sense
));
632 ata_command
= ATA_SMART_CMD
;
634 case CHECK_POWER_MODE
:
635 ata_command
= ATA_CHECK_POWER_MODE
;
639 case READ_VALUES
: /* READ DATA */
640 feature
= ATA_SMART_READ_VALUES
;
641 sector_count
= 1; /* one (512 byte) block */
642 t_length
= 2; /* sector count holds count */
645 case READ_THRESHOLDS
: /* obsolete */
646 feature
= ATA_SMART_READ_THRESHOLDS
;
647 sector_count
= 1; /* one (512 byte) block */
649 t_length
= 2; /* sector count holds count */
653 feature
= ATA_SMART_READ_LOG_SECTOR
;
654 sector_count
= 1; /* one (512 byte) block */
656 t_length
= 2; /* sector count holds count */
660 feature
= ATA_SMART_WRITE_LOG_SECTOR
;
661 sector_count
= 1; /* one (512 byte) block */
663 t_length
= 2; /* sector count holds count */
664 t_dir
= 0; /* to device */
668 ata_command
= ATA_IDENTIFY_DEVICE
;
669 sector_count
= 1; /* one (512 byte) block */
670 t_length
= 2; /* sector count holds count */
674 ata_command
= ATA_IDENTIFY_PACKET_DEVICE
;
675 sector_count
= 1; /* one (512 byte) block */
676 t_length
= 2; /* sector count (7:0) holds count */
680 feature
= ATA_SMART_ENABLE
;
684 feature
= ATA_SMART_DISABLE
;
688 // this command only says if SMART is working. It could be
689 // replaced with STATUS_CHECK below.
690 feature
= ATA_SMART_STATUS
;
694 feature
= ATA_SMART_AUTO_OFFLINE
;
695 sector_count
= select
; // YET NOTE - THIS IS A NON-DATA COMMAND!!
698 feature
= ATA_SMART_AUTOSAVE
;
699 sector_count
= select
; // YET NOTE - THIS IS A NON-DATA COMMAND!!
701 case IMMEDIATE_OFFLINE
:
702 feature
= ATA_SMART_IMMEDIATE_OFFLINE
;
706 // This command uses HDIO_DRIVE_TASK and has different syntax than
707 // the other commands.
708 feature
= ATA_SMART_STATUS
; /* SMART RETURN STATUS */
712 pout("Unrecognized command %d in usbcypress_device::ata_command_interface()\n"
713 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
717 if (ATA_SMART_CMD
== ata_command
) {
722 cdb
[0] = m_signature
; // bVSCBSignature : vendor-specific command
723 cdb
[1] = 0x24; // bVSCBSubCommand : 0x24 for ATACB
725 if (ata_command
== ATA_IDENTIFY_DEVICE
|| ata_command
== ATA_IDENTIFY_PACKET_DEVICE
)
726 cdb
[2] |= (1<<7); //set IdentifyPacketDevice for these cmds
727 cdb
[3] = 0xff - (1<<0) - (1<<6); //features, sector count, lba low, lba med
728 // lba high, command are valid
729 cdb
[4] = byte_block
; //TransferBlockCount : 512
733 cdb
[7] = sector_count
;
737 cdb
[12] = ata_command
;
739 memset(&io_hdr
, 0, sizeof(io_hdr
));
741 io_hdr
.dxfer_dir
= DXFER_NONE
;
742 io_hdr
.dxfer_len
= 0;
743 } else if (t_dir
) { /* from device */
744 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
745 io_hdr
.dxfer_len
= copydata
;
746 io_hdr
.dxferp
= (unsigned char *)data
;
747 memset(data
, 0, copydata
); /* prefill with zeroes */
748 } else { /* to device */
749 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
750 io_hdr
.dxfer_len
= outlen
;
751 io_hdr
.dxferp
= (unsigned char *)data
;
754 io_hdr
.cmnd_len
= passthru_size
;
755 io_hdr
.sensep
= sense
;
756 io_hdr
.max_sense_len
= sizeof(sense
);
757 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
759 scsi_device
* scsidev
= get_tunnel_dev();
760 if (!scsidev
->scsi_pass_through(&io_hdr
)) {
761 if (scsi_debugmode
> 0)
762 pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
763 "errno=%d [%s]\n", scsidev
->get_errno(), scsidev
->get_errmsg());
764 set_err(scsidev
->get_err());
768 // if there is a sense the command failed or the
769 // device doesn't support usbcypress
770 if (io_hdr
.scsi_status
== SCSI_STATUS_CHECK_CONDITION
&&
771 sg_scsi_normalize_sense(io_hdr
.sensep
, io_hdr
.resp_sense_len
, NULL
)) {
775 unsigned char ardp
[8];
777 /* XXX this is racy if there other scsi command between
778 * the first usbcypress command and this one
780 //pout("If you got strange result, please retry without traffic on the disc\n");
781 /* we use the same command as before, but we set
782 * * the read taskfile bit, for not executing usbcypress command,
783 * * but reading register selected in srb->cmnd[4]
785 cdb
[2] = (1<<0); /* ask read taskfile */
786 memset(sense
, 0, sizeof(sense
));
788 /* transfert 8 bytes */
789 memset(&io_hdr
, 0, sizeof(io_hdr
));
790 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
791 io_hdr
.dxfer_len
= ard_len
;
792 io_hdr
.dxferp
= (unsigned char *)ardp
;
793 memset(ardp
, 0, ard_len
); /* prefill with zeroes */
796 io_hdr
.cmnd_len
= passthru_size
;
797 io_hdr
.sensep
= sense
;
798 io_hdr
.max_sense_len
= sizeof(sense
);
799 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
802 if (!scsidev
->scsi_pass_through(&io_hdr
)) {
803 if (scsi_debugmode
> 0)
804 pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
805 "errno=%d [%s]\n", scsidev
->get_errno(), scsidev
->get_errmsg());
806 set_err(scsidev
->get_err());
809 // if there is a sense the command failed or the
810 // device doesn't support usbcypress
811 if (io_hdr
.scsi_status
== SCSI_STATUS_CHECK_CONDITION
&&
812 sg_scsi_normalize_sense(io_hdr
.sensep
, io_hdr
.resp_sense_len
, NULL
)) {
817 if (scsi_debugmode
> 1) {
818 pout("Values from ATA Return Descriptor are:\n");
819 dStrHex((const char *)ardp
, ard_len
, 1);
822 if (ATA_CHECK_POWER_MODE
== ata_command
)
823 data
[0] = ardp
[2]; /* sector count (0:7) */
824 else if (STATUS_CHECK
== command
) {
825 if ((ardp
[4] == 0x4f) && (ardp
[5] == 0xc2))
826 return 0; /* GOOD smart status */
827 if ((ardp
[4] == 0xf4) && (ardp
[5] == 0x2c))
828 return 1; // smart predicting failure, "bad" status
829 // We haven't gotten output that makes sense so
830 // print out some debugging info
831 syserror("Error SMART Status command failed");
832 pout("This may be due to a race in usbcypress\n");
833 pout("Retry without other disc access\n");
834 pout("Please get assistance from " PACKAGE_HOMEPAGE
"\n");
835 pout("Values from ATA Return Descriptor are:\n");
836 dStrHex((const char *)ardp
, ard_len
, 1);
843 #if 0 // Not used, see autodetect_sat_device() below.
844 static int isprint_string(const char *s
)
847 if (isprint(*s
) == 0)
854 /* Attempt an IDENTIFY DEVICE ATA or IDENTIFY PACKET DEVICE command
855 If successful return 1, else 0 */
856 // TODO: Combine with has_sat_pass_through above
857 static int has_usbcypress_pass_through(ata_device
* atadev
, const char *manufacturer
, const char *product
)
859 struct ata_identify_device drive
;
860 char model
[40], serial
[20], firm
[8];
862 /* issue the command and do a checksum if possible */
863 if (ataReadHDIdentity(atadev
, &drive
) < 0)
866 /* check if model string match, revision doesn't work for me */
867 format_ata_string(model
, drive
.model
, 40);
868 if (*model
== 0 || isprint_string(model
) == 0)
871 if (manufacturer
&& strncmp(manufacturer
, model
, 8))
872 pout("manufacturer doesn't match in pass_through test\n");
874 strlen(model
) > 8 && strncmp(product
, model
+8, strlen(model
)-8))
875 pout("product doesn't match in pass_through test\n");
878 format_ata_string(serial
, drive
.serial_no
, 20);
879 if (isprint_string(serial
) == 0)
881 format_ata_string(firm
, drive
.fw_rev
, 8);
882 if (isprint_string(firm
) == 0)
888 /////////////////////////////////////////////////////////////////////////////
890 /// JMicron USB Bridge support.
892 class usbjmicron_device
893 : public tunnelled_device
<
894 /*implements*/ ata_device
,
895 /*by tunnelling through a*/ scsi_device
899 usbjmicron_device(smart_interface
* intf
, scsi_device
* scsidev
,
900 const char * req_type
, bool prolific
,
901 bool ata_48bit_support
, int port
);
903 virtual ~usbjmicron_device() throw();
907 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
910 bool get_registers(unsigned short addr
, unsigned char * buf
, unsigned short size
);
913 bool m_ata_48bit_support
;
918 usbjmicron_device::usbjmicron_device(smart_interface
* intf
, scsi_device
* scsidev
,
919 const char * req_type
, bool prolific
,
920 bool ata_48bit_support
, int port
)
921 : smart_device(intf
, scsidev
->get_dev_name(), "usbjmicron", req_type
),
922 tunnelled_device
<ata_device
, scsi_device
>(scsidev
),
923 m_prolific(prolific
), m_ata_48bit_support(ata_48bit_support
),
924 m_port(port
>= 0 || !prolific
? port
: 0)
926 set_info().info_name
= strprintf("%s [USB JMicron]", scsidev
->get_info_name());
929 usbjmicron_device::~usbjmicron_device() throw()
934 bool usbjmicron_device::open()
937 if (!tunnelled_device
<ata_device
, scsi_device
>::open())
940 // Detect port if not specified
942 unsigned char regbuf
[1] = {0};
943 if (!get_registers(0x720f, regbuf
, sizeof(regbuf
))) {
948 switch (regbuf
[0] & 0x44) {
955 return set_err(EINVAL
, "Two devices connected, try '-d usbjmicron,[01]'");
958 return set_err(ENODEV
, "No device connected");
966 bool usbjmicron_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
968 if (!ata_cmd_is_supported(in
,
969 ata_device::supports_data_out
|
970 ata_device::supports_smart_status
|
971 (m_ata_48bit_support
? ata_device::supports_48bit_hi_null
: 0),
977 return set_err(EIO
, "Unknown JMicron port");
980 memset(&io_hdr
, 0, sizeof(io_hdr
));
983 unsigned char smart_status
= 0xff;
985 bool is_smart_status
= ( in
.in_regs
.command
== ATA_SMART_CMD
986 && in
.in_regs
.features
== ATA_SMART_STATUS
);
988 if (is_smart_status
&& in
.out_needed
.is_set()) {
989 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
990 io_hdr
.dxfer_len
= 1;
991 io_hdr
.dxferp
= &smart_status
;
993 else switch (in
.direction
) {
994 case ata_cmd_in::no_data
:
995 io_hdr
.dxfer_dir
= DXFER_NONE
;
997 case ata_cmd_in::data_in
:
998 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
999 io_hdr
.dxfer_len
= in
.size
;
1000 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
1001 memset(in
.buffer
, 0, in
.size
);
1003 case ata_cmd_in::data_out
:
1004 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
1005 io_hdr
.dxfer_len
= in
.size
;
1006 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
1010 return set_err(EINVAL
);
1013 // Build pass through command
1014 unsigned char cdb
[14];
1016 cdb
[ 1] = (rwbit
? 0x10 : 0x00);
1018 cdb
[ 3] = (unsigned char)(io_hdr
.dxfer_len
>> 8);
1019 cdb
[ 4] = (unsigned char)(io_hdr
.dxfer_len
);
1020 cdb
[ 5] = in
.in_regs
.features
;
1021 cdb
[ 6] = in
.in_regs
.sector_count
;
1022 cdb
[ 7] = in
.in_regs
.lba_low
;
1023 cdb
[ 8] = in
.in_regs
.lba_mid
;
1024 cdb
[ 9] = in
.in_regs
.lba_high
;
1025 cdb
[10] = in
.in_regs
.device
| (m_port
== 0 ? 0xa0 : 0xb0);
1026 cdb
[11] = in
.in_regs
.command
;
1032 io_hdr
.cmnd_len
= (!m_prolific
? 12 : 14);
1034 scsi_device
* scsidev
= get_tunnel_dev();
1035 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1036 "usbjmicron_device::ata_pass_through: "))
1037 return set_err(scsidev
->get_err());
1039 if (in
.out_needed
.is_set()) {
1040 if (is_smart_status
) {
1041 if (io_hdr
.resid
== 1)
1042 // Some (Prolific) USB bridges do not transfer a status byte
1043 return set_err(ENOSYS
, "Incomplete response, status byte missing [JMicron]");
1045 switch (smart_status
) {
1047 out
.out_regs
.lba_high
= 0xc2;
1048 out
.out_regs
.lba_mid
= 0x4f;
1051 out
.out_regs
.lba_high
= 0x2c;
1052 out
.out_regs
.lba_mid
= 0xf4;
1055 // Some (JM20336) USB bridges always return 0x01, regardless of SMART Status
1056 return set_err(ENOSYS
, "Invalid status byte (0x%02x) [JMicron]", smart_status
);
1060 #if 0 // Not needed for SMART STATUS, see also notes below
1062 // Read ATA output registers
1063 // NOTE: The register addresses are not valid for some older chip revisions
1064 // NOTE: There is a small race condition here!
1065 unsigned char regbuf
[16] = {0, };
1066 if (!get_registers((m_port
== 0 ? 0x8000 : 0x9000), regbuf
, sizeof(regbuf
)))
1069 out
.out_regs
.sector_count
= regbuf
[ 0];
1070 out
.out_regs
.lba_mid
= regbuf
[ 4];
1071 out
.out_regs
.lba_low
= regbuf
[ 6];
1072 out
.out_regs
.device
= regbuf
[ 9];
1073 out
.out_regs
.lba_high
= regbuf
[10];
1074 out
.out_regs
.error
= regbuf
[13];
1075 out
.out_regs
.status
= regbuf
[14];
1083 bool usbjmicron_device::get_registers(unsigned short addr
,
1084 unsigned char * buf
, unsigned short size
)
1086 unsigned char cdb
[14];
1090 cdb
[ 3] = (unsigned char)(size
>> 8);
1091 cdb
[ 4] = (unsigned char)(size
);
1093 cdb
[ 6] = (unsigned char)(addr
>> 8);
1094 cdb
[ 7] = (unsigned char)(addr
);
1103 scsi_cmnd_io io_hdr
;
1104 memset(&io_hdr
, 0, sizeof(io_hdr
));
1105 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
1106 io_hdr
.dxfer_len
= size
;
1107 io_hdr
.dxferp
= buf
;
1109 io_hdr
.cmnd_len
= sizeof(cdb
);
1110 io_hdr
.cmnd_len
= (!m_prolific
? 12 : 14);
1112 scsi_device
* scsidev
= get_tunnel_dev();
1113 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1114 "usbjmicron_device::get_registers: "))
1115 return set_err(scsidev
->get_err());
1121 /////////////////////////////////////////////////////////////////////////////
1123 /// SunplusIT USB Bridge support.
1125 class usbsunplus_device
1126 : public tunnelled_device
<
1127 /*implements*/ ata_device
,
1128 /*by tunnelling through a*/ scsi_device
1132 usbsunplus_device(smart_interface
* intf
, scsi_device
* scsidev
,
1133 const char * req_type
);
1135 virtual ~usbsunplus_device() throw();
1137 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
1141 usbsunplus_device::usbsunplus_device(smart_interface
* intf
, scsi_device
* scsidev
,
1142 const char * req_type
)
1143 : smart_device(intf
, scsidev
->get_dev_name(), "usbsunplus", req_type
),
1144 tunnelled_device
<ata_device
, scsi_device
>(scsidev
)
1146 set_info().info_name
= strprintf("%s [USB Sunplus]", scsidev
->get_info_name());
1149 usbsunplus_device::~usbsunplus_device() throw()
1153 bool usbsunplus_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
1155 if (!ata_cmd_is_supported(in
,
1156 ata_device::supports_data_out
|
1157 ata_device::supports_output_regs
|
1158 ata_device::supports_48bit
,
1163 scsi_cmnd_io io_hdr
;
1164 unsigned char cdb
[12];
1166 if (in
.in_regs
.is_48bit_cmd()) {
1167 // Set "previous" registers
1168 memset(&io_hdr
, 0, sizeof(io_hdr
));
1169 io_hdr
.dxfer_dir
= DXFER_NONE
;
1173 cdb
[ 2] = 0x23; // Subcommand: Pass through presetting
1176 cdb
[ 5] = in
.in_regs
.prev
.features
;
1177 cdb
[ 6] = in
.in_regs
.prev
.sector_count
;
1178 cdb
[ 7] = in
.in_regs
.prev
.lba_low
;
1179 cdb
[ 8] = in
.in_regs
.prev
.lba_mid
;
1180 cdb
[ 9] = in
.in_regs
.prev
.lba_high
;
1185 io_hdr
.cmnd_len
= sizeof(cdb
);
1187 scsi_device
* scsidev
= get_tunnel_dev();
1188 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1189 "usbsunplus_device::scsi_pass_through (presetting): "))
1190 return set_err(scsidev
->get_err());
1193 // Run Pass through command
1194 memset(&io_hdr
, 0, sizeof(io_hdr
));
1195 unsigned char protocol
;
1196 switch (in
.direction
) {
1197 case ata_cmd_in::no_data
:
1198 io_hdr
.dxfer_dir
= DXFER_NONE
;
1201 case ata_cmd_in::data_in
:
1202 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
1203 io_hdr
.dxfer_len
= in
.size
;
1204 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
1205 memset(in
.buffer
, 0, in
.size
);
1208 case ata_cmd_in::data_out
:
1209 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
1210 io_hdr
.dxfer_len
= in
.size
;
1211 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
1215 return set_err(EINVAL
);
1220 cdb
[ 2] = 0x22; // Subcommand: Pass through
1222 cdb
[ 4] = (unsigned char)(io_hdr
.dxfer_len
>> 9);
1223 cdb
[ 5] = in
.in_regs
.features
;
1224 cdb
[ 6] = in
.in_regs
.sector_count
;
1225 cdb
[ 7] = in
.in_regs
.lba_low
;
1226 cdb
[ 8] = in
.in_regs
.lba_mid
;
1227 cdb
[ 9] = in
.in_regs
.lba_high
;
1228 cdb
[10] = in
.in_regs
.device
| 0xa0;
1229 cdb
[11] = in
.in_regs
.command
;
1232 io_hdr
.cmnd_len
= sizeof(cdb
);
1234 scsi_device
* scsidev
= get_tunnel_dev();
1235 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1236 "usbsunplus_device::scsi_pass_through: "))
1237 // Returns sense key 0x03 (medium error) on ATA command error
1238 return set_err(scsidev
->get_err());
1240 if (in
.out_needed
.is_set()) {
1241 // Read ATA output registers
1242 unsigned char regbuf
[8] = {0, };
1243 memset(&io_hdr
, 0, sizeof(io_hdr
));
1244 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
1245 io_hdr
.dxfer_len
= sizeof(regbuf
);
1246 io_hdr
.dxferp
= regbuf
;
1250 cdb
[ 2] = 0x21; // Subcommand: Get status
1251 memset(cdb
+3, 0, sizeof(cdb
)-3);
1253 io_hdr
.cmnd_len
= sizeof(cdb
);
1255 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1256 "usbsunplus_device::scsi_pass_through (get registers): "))
1257 return set_err(scsidev
->get_err());
1259 out
.out_regs
.error
= regbuf
[1];
1260 out
.out_regs
.sector_count
= regbuf
[2];
1261 out
.out_regs
.lba_low
= regbuf
[3];
1262 out
.out_regs
.lba_mid
= regbuf
[4];
1263 out
.out_regs
.lba_high
= regbuf
[5];
1264 out
.out_regs
.device
= regbuf
[6];
1265 out
.out_regs
.status
= regbuf
[7];
1274 using namespace sat
;
1277 /////////////////////////////////////////////////////////////////////////////
1279 // Return ATA->SCSI filter for SAT or USB.
1281 ata_device
* smart_interface::get_sat_device(const char * type
, scsi_device
* scsidev
)
1283 if (!strncmp(type
, "sat", 3)) {
1284 const char * t
= type
+ 3;
1285 bool enable_auto
= false;
1286 if (!strncmp(t
, ",auto", 5)) {
1290 int ptlen
= 0, n
= -1;
1291 if (*t
&& !(sscanf(t
, ",%d%n", &ptlen
, &n
) == 1 && n
== (int)strlen(t
)
1292 && (ptlen
== 0 || ptlen
== 12 || ptlen
== 16))) {
1293 set_err(EINVAL
, "Option '-d sat[,auto][,N]' requires N to be 0, 12 or 16");
1296 return new sat_device(this, scsidev
, type
, ptlen
, enable_auto
);
1299 else if (!strncmp(type
, "usbcypress", 10)) {
1300 unsigned signature
= 0x24; int n1
= -1, n2
= -1;
1301 if (!(((sscanf(type
, "usbcypress%n,0x%x%n", &n1
, &signature
, &n2
) == 1 && n2
== (int)strlen(type
)) || n1
== (int)strlen(type
))
1302 && signature
<= 0xff)) {
1303 set_err(EINVAL
, "Option '-d usbcypress,<n>' requires <n> to be "
1304 "an hexadecimal number between 0x0 and 0xff");
1307 return new usbcypress_device(this, scsidev
, type
, signature
);
1310 else if (!strncmp(type
, "usbjmicron", 10)) {
1311 const char * t
= type
+ 10;
1312 bool prolific
= false;
1313 if (!strncmp(t
, ",p", 2)) {
1317 bool ata_48bit_support
= false;
1318 if (!strncmp(t
, ",x", 2)) {
1320 ata_48bit_support
= true;
1322 int port
= -1, n
= -1;
1323 if (*t
&& !( (sscanf(t
, ",%d%n", &port
, &n
) == 1
1324 && n
== (int)strlen(t
) && 0 <= port
&& port
<= 1))) {
1325 set_err(EINVAL
, "Option '-d usbjmicron[,p][,x],<n>' requires <n> to be 0 or 1");
1328 return new usbjmicron_device(this, scsidev
, type
, prolific
, ata_48bit_support
, port
);
1331 else if (!strcmp(type
, "usbsunplus")) {
1332 return new usbsunplus_device(this, scsidev
, type
);
1336 set_err(EINVAL
, "Unknown USB device type '%s'", type
);
1341 // Try to detect a SAT device behind a SCSI interface.
1343 ata_device
* smart_interface::autodetect_sat_device(scsi_device
* scsidev
,
1344 const unsigned char * inqdata
, unsigned inqsize
)
1346 if (!scsidev
->is_open())
1350 if (inqdata
&& inqsize
>= 36 && !memcmp(inqdata
+ 8, "ATA ", 8)) { // TODO: Linux-specific?
1351 ata_device_auto_ptr
atadev( new sat_device(this, scsidev
, "") , scsidev
);
1352 if (has_sat_pass_through(atadev
.get()))
1353 return atadev
.release(); // Detected SAT
1360 /////////////////////////////////////////////////////////////////////////////
1361 // USB device type detection
1363 // Format USB ID for error messages
1364 static std::string
format_usb_id(int vendor_id
, int product_id
, int version
)
1367 return strprintf("[0x%04x:0x%04x (0x%03x)]", vendor_id
, product_id
, version
);
1369 return strprintf("[0x%04x:0x%04x]", vendor_id
, product_id
);
1372 // Get type name for USB device with known VENDOR:PRODUCT ID.
1373 const char * smart_interface::get_usb_dev_type_by_id(int vendor_id
, int product_id
,
1374 int version
/*= -1*/)
1376 usb_dev_info info
, info2
;
1377 int n
= lookup_usb_device(vendor_id
, product_id
, version
, info
, info2
);
1380 set_err(EINVAL
, "Unknown USB bridge %s",
1381 format_usb_id(vendor_id
, product_id
, version
).c_str());
1386 set_err(EINVAL
, "USB bridge %s type is ambiguous: '%s' or '%s'",
1387 format_usb_id(vendor_id
, product_id
, version
).c_str(),
1388 (!info
.usb_type
.empty() ? info
.usb_type
.c_str() : "[unsupported]"),
1389 (!info2
.usb_type
.empty() ? info2
.usb_type
.c_str() : "[unsupported]"));
1393 if (info
.usb_type
.empty()) {
1394 set_err(ENOSYS
, "Unsupported USB bridge %s",
1395 format_usb_id(vendor_id
, product_id
, version
).c_str());
1399 // TODO: change return type to std::string
1400 static std::string type
;
1401 type
= info
.usb_type
;
1402 return type
.c_str();