aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2022-07-11 18:16:30 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2022-07-11 18:16:30 +0000
commita51fa77e373d1e4a1be10e8e4ef9a87547d26e86 (patch)
tree88b59744783292c3f8ec8d8906cd723c5900e375
parent5e6f4a6ba05f122b39407f2bdb8d8bea194b8990 (diff)
downloadsg3_utils-a51fa77e373d1e4a1be10e8e4ef9a87547d26e86.tar.gz
sg_inq+sg_vpd: merge VPD page processing
This is being done so that ongoing JSON work is not duplicated for both sg_vpd and sg_inq. This might lead to small changes in formatting of VPD (and standard INQUIRY) output. That in turn might break parsing code expecting the former output. Hopefully this will push folks who are parsing to try out JSON output. However JSON output format may not be that stable, hoping for feedback on that front. git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@959 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog7
-rw-r--r--doc/scsi_mandat.82
-rw-r--r--doc/scsi_readcap.82
-rw-r--r--doc/scsi_ready.82
-rw-r--r--doc/scsi_satl.82
-rw-r--r--doc/scsi_start.82
-rw-r--r--doc/scsi_stop.82
-rw-r--r--doc/scsi_temperature.82
-rw-r--r--doc/sg3_utils.88
-rw-r--r--doc/sg3_utils_json.899
-rw-r--r--doc/sg_bg_ctl.82
-rw-r--r--doc/sg_copy_results.82
-rw-r--r--doc/sg_decode_sense.82
-rw-r--r--doc/sg_get_config.82
-rw-r--r--doc/sg_get_elem_status.82
-rw-r--r--doc/sg_get_lba_status.82
-rw-r--r--doc/sg_ident.82
-rw-r--r--doc/sg_inq.85
-rw-r--r--doc/sg_luns.82
-rw-r--r--doc/sg_map26.82
-rw-r--r--doc/sg_prevent.82
-rw-r--r--doc/sg_read_attr.82
-rw-r--r--doc/sg_read_block_limits.82
-rw-r--r--doc/sg_read_buffer.82
-rw-r--r--doc/sg_reassign.82
-rw-r--r--doc/sg_referrals.82
-rw-r--r--doc/sg_rem_rest_elem.82
-rw-r--r--doc/sg_rep_density.82
-rw-r--r--doc/sg_rep_pip.82
-rw-r--r--doc/sg_rep_zones.82
-rw-r--r--doc/sg_requests.82
-rw-r--r--doc/sg_reset_wp.82
-rw-r--r--doc/sg_rmsn.82
-rw-r--r--doc/sg_rtpg.82
-rw-r--r--doc/sg_safte.82
-rw-r--r--doc/sg_sanitize.82
-rw-r--r--doc/sg_sat_identify.82
-rw-r--r--doc/sg_sat_phy_event.82
-rw-r--r--doc/sg_sat_read_gplog.82
-rw-r--r--doc/sg_sat_set_features.82
-rw-r--r--doc/sg_seek.82
-rw-r--r--doc/sg_ses.82
-rw-r--r--doc/sg_ses_microcode.82
-rw-r--r--doc/sg_stpg.82
-rw-r--r--doc/sg_stream_ctl.82
-rw-r--r--doc/sg_sync.82
-rw-r--r--doc/sg_timestamp.82
-rw-r--r--doc/sg_unmap.82
-rw-r--r--doc/sg_verify.82
-rw-r--r--doc/sg_vpd.82
-rw-r--r--doc/sg_wr_mode.82
-rw-r--r--doc/sg_write_buffer.82
-rw-r--r--doc/sg_write_same.82
-rw-r--r--doc/sg_write_verify.82
-rw-r--r--doc/sg_write_x.82
-rw-r--r--doc/sg_z_act_query.82
-rw-r--r--doc/sg_zone.82
-rw-r--r--include/sg_lib.h6
-rw-r--r--include/sg_pr2serr.h45
-rw-r--r--lib/sg_pr2serr.c376
-rw-r--r--src/Makefile.am4
-rw-r--r--src/Makefile.in27
-rw-r--r--src/sg_decode_sense.c4
-rw-r--r--src/sg_inq.c998
-rw-r--r--src/sg_vpd.c731
-rw-r--r--src/sg_vpd.h80
-rw-r--r--src/sg_vpd_common.c558
-rw-r--r--src/sg_vpd_common.h205
-rw-r--r--src/sg_vpd_vendor.c2
-rw-r--r--testing/tst_sg_lib.c26
70 files changed, 1868 insertions, 1419 deletions
diff --git a/ChangeLog b/ChangeLog
index 800c2e01..6f009755 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for pre-release sg3_utils-1.48 [20220705] [svn: r958]
+Changelog for pre-release sg3_utils-1.48 [20220711] [svn: r959]
- some utilities: add experimental --json[=JO] option
- sg_z_act_query: new utility for sending either a
Zone activate or Zone query command
@@ -44,8 +44,9 @@ Changelog for pre-release sg3_utils-1.48 [20220705] [svn: r958]
- improve 'last_n' log pages; supply VPD and mode pages
with their name (if T10 defined)
- sg_modes: improve handling of zbc disks with pdt=0x14
- - sg_inq, sg_vpd: Device Identication VPD page, change
- "IEEE Company_id" to "AOI" as per spc6r06.pdf
+ - sg_inq, sg_vpd: merge VPD page processing
+ - Device Identication VPD page, change
+ "IEEE Company_id" to "AOI" as per spc6r06.pdf
- add support for Hitachi/HP open-v ldev names
- sg_vpd: apply github pull 18 (missing LF)
- sg_opcodes: cleanup error reporting
diff --git a/doc/scsi_mandat.8 b/doc/scsi_mandat.8
index 76068617..95a708c6 100644
--- a/doc/scsi_mandat.8
+++ b/doc/scsi_mandat.8
@@ -38,7 +38,7 @@ Written by D. Gilbert
.SH COPYRIGHT
Copyright \(co 2011\-2013 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_inq,sg_luns,sg_turs,sg_requests,sg_vpd,sg_senddiag (sg3_utils)
diff --git a/doc/scsi_readcap.8 b/doc/scsi_readcap.8
index 40532b01..d898ce9c 100644
--- a/doc/scsi_readcap.8
+++ b/doc/scsi_readcap.8
@@ -45,7 +45,7 @@ Written by D. Gilbert
.SH COPYRIGHT
Copyright \(co 2009\-2013 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_readcap (sg3_utils)
diff --git a/doc/scsi_ready.8 b/doc/scsi_ready.8
index 50a6ed74..e0548e06 100644
--- a/doc/scsi_ready.8
+++ b/doc/scsi_ready.8
@@ -34,7 +34,7 @@ Written by D. Gilbert
.SH COPYRIGHT
Copyright \(co 2009\-2013 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_turs (sg3_utils)
diff --git a/doc/scsi_satl.8 b/doc/scsi_satl.8
index da6c43a3..bddee9fc 100644
--- a/doc/scsi_satl.8
+++ b/doc/scsi_satl.8
@@ -37,7 +37,7 @@ Written by D. Gilbert
.SH COPYRIGHT
Copyright \(co 2011\-2013 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_inq, sg_luns, sg_turs, sg_requests, sg_vpd, sg_senddiag, sg_modes,
diff --git a/doc/scsi_start.8 b/doc/scsi_start.8
index f98985b2..72682321 100644
--- a/doc/scsi_start.8
+++ b/doc/scsi_start.8
@@ -34,7 +34,7 @@ Written by D. Gilbert
.SH COPYRIGHT
Copyright \(co 2009\-2013 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_start (sg3_utils)
diff --git a/doc/scsi_stop.8 b/doc/scsi_stop.8
index 488c7cf7..79b7b2fd 100644
--- a/doc/scsi_stop.8
+++ b/doc/scsi_stop.8
@@ -35,7 +35,7 @@ Written by D. Gilbert
.SH COPYRIGHT
Copyright \(co 2009\-2013 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_start (sg3_utils)
diff --git a/doc/scsi_temperature.8 b/doc/scsi_temperature.8
index e9ff181c..e3ce56b6 100644
--- a/doc/scsi_temperature.8
+++ b/doc/scsi_temperature.8
@@ -29,7 +29,7 @@ Written by D. Gilbert
.SH COPYRIGHT
Copyright \(co 2011\-2013 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_logs (sg3_utils)
diff --git a/doc/sg3_utils.8 b/doc/sg3_utils.8
index c210ccae..92fd1d33 100644
--- a/doc/sg3_utils.8
+++ b/doc/sg3_utils.8
@@ -853,12 +853,12 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 1999\-2022 Douglas Gilbert
.br
-Some utilities are distributed under a GPL version 2 license while
-others, usually more recent ones, are under a FreeBSD license. The files
+Some utilities are distributed under a GPL version 2 license while others,
+usually more recent ones, are under a BSD\-2\-Clause license. The files
that are common to almost all utilities and thus contain the most reusable
code, namely sg_lib.[hc], sg_cmds_basic.[hc] and sg_cmds_extra.[hc] are
-under a FreeBSD license. There is NO warranty; not even for MERCHANTABILITY
-or FITNESS FOR A PARTICULAR PURPOSE.
+under a BSD\-2\-Clause license. There is NO warranty; not even for
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg3_utils_json,sg_decode_sense(sg3_utils), sdparm(sdparm), ddpt(ddpt),
.B lsscsi(lsscsi), dmesg(1), mt(1)
diff --git a/doc/sg3_utils_json.8 b/doc/sg3_utils_json.8
index 454dfa7a..0d437470 100644
--- a/doc/sg3_utils_json.8
+++ b/doc/sg3_utils_json.8
@@ -97,23 +97,6 @@ defined to make the short option form look better (e.g. '\-j=av').
negation character. Toggles the (boolean) sense of the following control
character.
.TP
-\fBa\fR
-this is a boolean control character for "abbreviated name expansion". T10
-names fields often depending on the amount of space available in the
-CDB (command descriptor block) table in the relevant specification. This
-leads to some clear names (e.g. "number of blocks) and some not so clear
-names (e.g. "SKSV"). When this character is on (true), then fields that have
-abbreviated names (subjective decision by author) will use the T10 field
-name with a sub\-object containing at least a "i" field with the integer
-value and a "abbreviated_name_expansion" field with a string value that
-should make the T10 name clearer (e.g. "Sense Key Specific Valid").
-.br
-The "abbreviated name expansion" control character is also used to flag
-fields that are obsolete, usually noting the standard or revision of a
-draft standard when they became obsolete.
-.br
-This boolean control character is default off (false).
-.TP
\fBe\fR
this is a boolean control character for "exit status". If active an "exit
status" field is placed at the end of the JSON output. The integer value
@@ -162,12 +145,24 @@ of 'normal' output.
.br
This boolean control character is default on (true).
.TP
+\fBn\fR
+this is a boolean control character for "name_extra". It is used to provide
+additional information about the name it is a sub\-object of. The most
+common usage is to spell out an abbreviated name (e.g. a T10 name like "SKSV"
+to "Sense Key Specific Valid"). Another use is to note that a T10 field is
+obsolete and in which T10 standard it first became obsolete. Also if the
+named field's value is a physical quantity where the unit is unclear (e.g. a
+timeout) then "name_extra" can state that (e.g. "unit: millisecond").
+Only some fields have associated "name_extra" data.
+.br
+This boolean control character is default off (false).
+.TP
\fBo\fR
this is a boolean control character to control whether normal (i.e.
non\-JSON) lines of output are placed in a JSON array (one element per
line of normal output) within the utility_invoked subject (see control
-character \fIl\fR). This control character is only active when the
-\fIl\fR control character is also active).
+character \fIl\fR). This control character is active even if the
+\fIl\fR control character is negated).
.br
This boolean control character is default off (false).
.TP
@@ -208,6 +203,63 @@ Note that this verbose control character is JSON specific while the
most utilities support is more general.
.br
This integer control character is set to 0 by default.
+.SH OUTPUT PROCESSING
+The default remains the same for all utilities that support the
+\fI\-\-json\fR option, namely the decoded information is sent to stdout in
+human readable form. Errors are reported to stderr and may cause the early
+termination of a utility (e.g. command line option syntax error).
+.PP
+When the \fI\-\-json\fR option is given and no errors are detected, then
+only JSON is sent to stdout. If the 'o' control character is in the \fIJO\fR
+argument to the \fI\-\-json\fR option, then the former "human readable"
+output is placed in a JSON array named "output" within a JSON object
+named "utility_invoked". Each line of the former "human readable" output
+is placed in its own element of the JSON array named "output".
+.PP
+A JSON tree is built in memory as the utility parses the data returned
+from the SCSI device (e.g. sg_vpd parsing a VPD page returned from a
+SCSI INQUIRY command). SCSI "list"s become JSON named arrays (e.g. in
+the Device Identification VPD page there is a "Designation descriptor
+list" that becomes a JSON array named "designation_descriptor_list").
+.PP
+At the completion of the utility that JSON tree is "measured" taking
+into account the form of output (i.e. pretty-printed, single line or
+packed single line). For the pretty-printed JSON output, the size of
+each indentation in spaces is also given (i.e. the tab width). The JSON
+is then output to a single C string, then sent to stdout. If a NULL
+character (ASCII zero and C string terminator) somehow finds its way
+into a field that should (according to the spec) be space padded, then
+the JSON output may appear truncated.
+.PP
+Note that this JSON processing means that if a utility is aborted for
+whatever reason then no JSON output will appear. With the normal,
+human readable output processing, some output may appear before
+the utility aborts in such bad situations.
+.SH ERRORS
+No attempts has been made to translate errors into JSON form, apart
+from the final "exit_status" JSON object where a value of 0
+means "no errors". Exit status values indicating a problem range
+from 1 to 255.
+.PP
+The sg_decode_sense utility will parse SCSI sense data into JSON
+form if requested. So if another utility is failing with a sense
+data report (most often seen when the \fI\-\-verbose\fR option is
+used). That sense data (in hex bytes) could be cut\-and\-paste
+onto the command line following 'sg_decode_sense \-j ' which should
+then render that sense data in JSON.
+.PP
+Otherwise, when a error is detected while JSON output is selected,
+the error message is sent to stderr in human readable form. Typically
+once an error is detected the utility will exit, first dumping
+the JSON in\-memory tree as discussed above and a non\-zero exit
+status will be set. The JSON output will be well formed but missing
+any fields or list elements following the point that the error
+was detected.
+.PP
+The summary is that when JSON output is selected and an error occurs
+each utility will process the error the same way as it would if JSON
+output had not been selected. In all cases error messages, in human
+readable form, are sent to stderr.
.SH AUTHORS
Written by Douglas Gilbert. Some utilities have been contributed, see the
CREDITS file and individual source files (in the 'src' directory).
@@ -216,11 +268,8 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2022 Douglas Gilbert
.br
-Some utilities are distributed under a GPL version 2 license while
-others, usually more recent ones, are under a FreeBSD license. The files
-that are common to almost all utilities and thus contain the most reusable
-code, namely sg_lib.[hc], sg_cmds_basic.[hc] and sg_cmds_extra.[hc] are
-under a FreeBSD license. There is NO warranty; not even for MERCHANTABILITY
-or FITNESS FOR A PARTICULAR PURPOSE.
+This software is distributed under the GPL version 2 or the BSD\-2\-Clause
+license. There is NO warranty; not even for MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg3_utils(sg3_utils), smartctl(smartmontools)
diff --git a/doc/sg_bg_ctl.8 b/doc/sg_bg_ctl.8
index 0aca9efa..98d56b44 100644
--- a/doc/sg_bg_ctl.8
+++ b/doc/sg_bg_ctl.8
@@ -66,7 +66,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2016 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_vpd,sg_logs(sg3_utils); sdparm(sdparm)
diff --git a/doc/sg_copy_results.8 b/doc/sg_copy_results.8
index 9e67e522..2e2203bf 100644
--- a/doc/sg_copy_results.8
+++ b/doc/sg_copy_results.8
@@ -120,7 +120,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2012\-2014 Hannes Reinecke and Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_xcopy(sg3_utils), ddpt,ddptctl(ddpt)
diff --git a/doc/sg_decode_sense.8 b/doc/sg_decode_sense.8
index 5680a075..2deaf0cd 100644
--- a/doc/sg_decode_sense.8
+++ b/doc/sg_decode_sense.8
@@ -178,7 +178,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2010\-2021 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_requests,sg_raw(sg3_utils)
diff --git a/doc/sg_get_config.8 b/doc/sg_get_config.8
index 4c4ea0c1..3716ed60 100644
--- a/doc/sg_get_config.8
+++ b/doc/sg_get_config.8
@@ -135,7 +135,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2004\-2012 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sginfo(8), sg_modes(8), sg_inq(8), sg_prevent(8),
diff --git a/doc/sg_get_elem_status.8 b/doc/sg_get_elem_status.8
index b9d7da11..8baad4fc 100644
--- a/doc/sg_get_elem_status.8
+++ b/doc/sg_get_elem_status.8
@@ -131,7 +131,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2019\-2022 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_get_lba_status,sg3_utils,sg3_utils_json(sg3_utils)
diff --git a/doc/sg_get_lba_status.8 b/doc/sg_get_lba_status.8
index 42288c4c..3f887aa3 100644
--- a/doc/sg_get_lba_status.8
+++ b/doc/sg_get_lba_status.8
@@ -155,7 +155,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2009\-2022 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_write_same,sg_unmap,sg3_utils,sg3_utils_json(sg3_utils)
diff --git a/doc/sg_ident.8 b/doc/sg_ident.8
index 76e0b31e..d36a176c 100644
--- a/doc/sg_ident.8
+++ b/doc/sg_ident.8
@@ -113,7 +113,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2005\-2018 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_vpd(sg3_utils), sg_rmsn(sg3_utils), sg_get_config(sg3_utils)
diff --git a/doc/sg_inq.8 b/doc/sg_inq.8
index 1e38f6a9..9ae5c550 100644
--- a/doc/sg_inq.8
+++ b/doc/sg_inq.8
@@ -528,8 +528,9 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2001\-2022 Douglas Gilbert
.br
-This software is distributed under the GPL version 2. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+This software is distributed under the GPL version 2 or the BSD\-2\-Clause
+license. There is NO warranty; not even for MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_opcodes(8), sg_vpd(8), sg_logs(8), sg_modes(8), sdparm(8), hdparm(8),
.B sgdiag(scsirastools)
diff --git a/doc/sg_luns.8 b/doc/sg_luns.8
index 82927726..3ededa9f 100644
--- a/doc/sg_luns.8
+++ b/doc/sg_luns.8
@@ -313,7 +313,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2004\-2020 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_inq(8)
diff --git a/doc/sg_map26.8 b/doc/sg_map26.8
index cb826e2b..7ad013bf 100644
--- a/doc/sg_map26.8
+++ b/doc/sg_map26.8
@@ -155,7 +155,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2005\-2012 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B udev(7), lsscsi(lsscsi)
diff --git a/doc/sg_prevent.8 b/doc/sg_prevent.8
index 3548ffba..d0cfb12c 100644
--- a/doc/sg_prevent.8
+++ b/doc/sg_prevent.8
@@ -53,7 +53,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2004\-2012 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_start(sg3_utils), sg_persist(sg3_utils)
diff --git a/doc/sg_read_attr.8 b/doc/sg_read_attr.8
index 85b459eb..8ab59b97 100644
--- a/doc/sg_read_attr.8
+++ b/doc/sg_read_attr.8
@@ -208,7 +208,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2016\-2020 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_vpd,sg_logs(sg3_utils)
diff --git a/doc/sg_read_block_limits.8 b/doc/sg_read_block_limits.8
index 1347acfb..5bdeb03a 100644
--- a/doc/sg_read_block_limits.8
+++ b/doc/sg_read_block_limits.8
@@ -54,7 +54,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2009\-2017 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg3_utils(sg3_utils)
diff --git a/doc/sg_read_buffer.8 b/doc/sg_read_buffer.8
index 09e39414..0acc9167 100644
--- a/doc/sg_read_buffer.8
+++ b/doc/sg_read_buffer.8
@@ -169,7 +169,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2006\-2019 Luben Tuikov and Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_write_buffer(sg3_utils)
diff --git a/doc/sg_reassign.8 b/doc/sg_reassign.8
index 3ad0f8a0..bbbea8cd 100644
--- a/doc/sg_reassign.8
+++ b/doc/sg_reassign.8
@@ -144,7 +144,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2005\-2019 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_format,sginfo,sg_senddiag(all in sg3_utils), sdparm(sdparm),
diff --git a/doc/sg_referrals.8 b/doc/sg_referrals.8
index f1371794..60111063 100644
--- a/doc/sg_referrals.8
+++ b/doc/sg_referrals.8
@@ -65,7 +65,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2009\-2014 Douglas Gilbert and Hannes Reinecke
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_vpd(8)
diff --git a/doc/sg_rem_rest_elem.8 b/doc/sg_rem_rest_elem.8
index 6300eef7..81c8aa2e 100644
--- a/doc/sg_rem_rest_elem.8
+++ b/doc/sg_rem_rest_elem.8
@@ -88,7 +88,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2022 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_get_elem_status,sg_zone(sg3_utils)
diff --git a/doc/sg_rep_density.8 b/doc/sg_rep_density.8
index 6734796a..f0633c4b 100644
--- a/doc/sg_rep_density.8
+++ b/doc/sg_rep_density.8
@@ -91,7 +91,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2022 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg3_utils(sg3_utils)
diff --git a/doc/sg_rep_pip.8 b/doc/sg_rep_pip.8
index fb615ee7..c614fd3f 100644
--- a/doc/sg_rep_pip.8
+++ b/doc/sg_rep_pip.8
@@ -52,7 +52,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2020\-2022 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg3_utils(sg3_utils)
diff --git a/doc/sg_rep_zones.8 b/doc/sg_rep_zones.8
index 71d101bc..8ab9feb5 100644
--- a/doc/sg_rep_zones.8
+++ b/doc/sg_rep_zones.8
@@ -207,7 +207,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2014\-2022 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_reset_wp,sg_zone,sg3_utils_json(sg3_utils),
diff --git a/doc/sg_requests.8 b/doc/sg_requests.8
index f6a012c5..e1c1605d 100644
--- a/doc/sg_requests.8
+++ b/doc/sg_requests.8
@@ -132,7 +132,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2004\-2021 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_turs (sg3_utils)
diff --git a/doc/sg_reset_wp.8 b/doc/sg_reset_wp.8
index ecc4ee6b..47d4453c 100644
--- a/doc/sg_reset_wp.8
+++ b/doc/sg_reset_wp.8
@@ -59,7 +59,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2014\-2022 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_rep_zones,sg_zone(sg3_utils)
diff --git a/doc/sg_rmsn.8 b/doc/sg_rmsn.8
index 294c85ae..7fc279ed 100644
--- a/doc/sg_rmsn.8
+++ b/doc/sg_rmsn.8
@@ -58,7 +58,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2005\-2012 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_vpd(sg3_utils), sg_get_config(sg3_utils)
diff --git a/doc/sg_rtpg.8 b/doc/sg_rtpg.8
index c4b8d5b1..d2ce33c3 100644
--- a/doc/sg_rtpg.8
+++ b/doc/sg_rtpg.8
@@ -58,7 +58,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2004\-2014 Christophe Varoqui and Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_inq(sg3_utils)
diff --git a/doc/sg_safte.8 b/doc/sg_safte.8
index 863a3426..c46a5b1a 100644
--- a/doc/sg_safte.8
+++ b/doc/sg_safte.8
@@ -126,7 +126,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2004\-2016 Hannes Reinecke and Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_inq, sg_ses (in sg3_utils package); safte\-monitor (internet)
diff --git a/doc/sg_sanitize.8 b/doc/sg_sanitize.8
index db8b74ca..bb7bdc4d 100644
--- a/doc/sg_sanitize.8
+++ b/doc/sg_sanitize.8
@@ -261,7 +261,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2011\-2020 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_requests(8), sg_format(8)
diff --git a/doc/sg_sat_identify.8 b/doc/sg_sat_identify.8
index e811614a..595321c9 100644
--- a/doc/sg_sat_identify.8
+++ b/doc/sg_sat_identify.8
@@ -161,7 +161,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2006\-2020 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_vpd(sg3_utils), sg_inq(sg3_utils), sdparm(sdparm), hdparm(hdparm)
diff --git a/doc/sg_sat_phy_event.8 b/doc/sg_sat_phy_event.8
index 8a2f14ae..8b842a3f 100644
--- a/doc/sg_sat_phy_event.8
+++ b/doc/sg_sat_phy_event.8
@@ -102,7 +102,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2006\-2020 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_sat_identify,sg_sat_read_gplog(sg3_utils),
diff --git a/doc/sg_sat_read_gplog.8 b/doc/sg_sat_read_gplog.8
index cb8f646f..552ad147 100644
--- a/doc/sg_sat_read_gplog.8
+++ b/doc/sg_sat_read_gplog.8
@@ -107,7 +107,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2014\-2015 Hannes Reinecke, SUSE Linux GmbH
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_sat_identify(sg3_utils), sg_inq(sg3_utils), sdparm(sdparm),
diff --git a/doc/sg_sat_set_features.8 b/doc/sg_sat_set_features.8
index d732c3de..304968fa 100644
--- a/doc/sg_sat_set_features.8
+++ b/doc/sg_sat_set_features.8
@@ -105,7 +105,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2007\-2014 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_sat_identify(sg3_utils), sg_inq(sg3_utils), sdparm(sdparm),
diff --git a/doc/sg_seek.8 b/doc/sg_seek.8
index 1b11f751..52ced593 100644
--- a/doc/sg_seek.8
+++ b/doc/sg_seek.8
@@ -140,7 +140,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2018 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_vpd(sg3_utils); sdparm(sdparm)
diff --git a/doc/sg_ses.8 b/doc/sg_ses.8
index 175e2fca..79c65978 100644
--- a/doc/sg_ses.8
+++ b/doc/sg_ses.8
@@ -794,7 +794,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2004\-2021 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_inq, sg_safte, sg_senddiag, sg_ses_microcode, sg3_utils (sg3_utils);
diff --git a/doc/sg_ses_microcode.8 b/doc/sg_ses_microcode.8
index 43e73ac2..70709681 100644
--- a/doc/sg_ses_microcode.8
+++ b/doc/sg_ses_microcode.8
@@ -273,7 +273,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2014\-2018 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_ses, sg_write_buffer, sg_inq(sg3_utils)
diff --git a/doc/sg_stpg.8 b/doc/sg_stpg.8
index 187054a5..5594878a 100644
--- a/doc/sg_stpg.8
+++ b/doc/sg_stpg.8
@@ -116,7 +116,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2007\-2014 Hannes Reinecke, Christophe Varoqui and Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_inq, sg_rtpg (sg3_utils)
diff --git a/doc/sg_stream_ctl.8 b/doc/sg_stream_ctl.8
index 8451cf55..18d9641c 100644
--- a/doc/sg_stream_ctl.8
+++ b/doc/sg_stream_ctl.8
@@ -111,7 +111,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2018 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_vpd,sg_write_x(sg3_utils); sdparm(sdparm)
diff --git a/doc/sg_sync.8 b/doc/sg_sync.8
index 64d3e479..77266184 100644
--- a/doc/sg_sync.8
+++ b/doc/sg_sync.8
@@ -91,7 +91,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2004\-2018 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_start(sg3_utils)
diff --git a/doc/sg_timestamp.8 b/doc/sg_timestamp.8
index f5c69553..dbc1ef16 100644
--- a/doc/sg_timestamp.8
+++ b/doc/sg_timestamp.8
@@ -149,7 +149,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2015\-2018 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sdparm(sdparm), sg_logs(sg3_utils)
diff --git a/doc/sg_unmap.8 b/doc/sg_unmap.8
index bd2e35f3..b72ecb05 100644
--- a/doc/sg_unmap.8
+++ b/doc/sg_unmap.8
@@ -160,7 +160,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2009\-2018 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_format,sg_get_lba_status,sg_readcap,sg_vpd,sg_write_same(sg3_utils)
diff --git a/doc/sg_verify.8 b/doc/sg_verify.8
index 7a55e1da..dae36042 100644
--- a/doc/sg_verify.8
+++ b/doc/sg_verify.8
@@ -212,7 +212,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2004\-2019 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sdparm(sdparm), sg_modes(sg3_utils), sg_readcap(sg3_utils),
diff --git a/doc/sg_vpd.8 b/doc/sg_vpd.8
index 53dd1808..842114ea 100644
--- a/doc/sg_vpd.8
+++ b/doc/sg_vpd.8
@@ -343,7 +343,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2006\-2022 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_inq(sg3_utils), sg3_utils(sg3_utils), sdparm(sdparm), hdparm(hdparm)
diff --git a/doc/sg_wr_mode.8 b/doc/sg_wr_mode.8
index c22be588..e917c76e 100644
--- a/doc/sg_wr_mode.8
+++ b/doc/sg_wr_mode.8
@@ -219,7 +219,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2004\-2018 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sdparm(sdparm), sg_modes(sg3_utils), sginfo(sg3_utils)
diff --git a/doc/sg_write_buffer.8 b/doc/sg_write_buffer.8
index 09332e1e..23913e37 100644
--- a/doc/sg_write_buffer.8
+++ b/doc/sg_write_buffer.8
@@ -221,7 +221,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2006\-2018 Luben Tuikov and Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_read_buffer, sg_ses_microcode(sg3_utils)
diff --git a/doc/sg_write_same.8 b/doc/sg_write_same.8
index 0e65dd9f..9d4c7049 100644
--- a/doc/sg_write_same.8
+++ b/doc/sg_write_same.8
@@ -348,7 +348,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2009\-2020 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_format,sg_get_lba_status,sg_readcap,sg_vpd,sg_unmap,
diff --git a/doc/sg_write_verify.8 b/doc/sg_write_verify.8
index f1837f95..6a784e0a 100644
--- a/doc/sg_write_verify.8
+++ b/doc/sg_write_verify.8
@@ -184,7 +184,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2014\-2018 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B ddpt(in a package of that name), sg_compare_and_write(8), sg_dd(8),
diff --git a/doc/sg_write_x.8 b/doc/sg_write_x.8
index e907c341..90fefc63 100644
--- a/doc/sg_write_x.8
+++ b/doc/sg_write_x.8
@@ -594,7 +594,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2017\-2021 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_readcap,sg_vpd,sg_write_same,sg_stream_ctl(sg3_utils)
diff --git a/doc/sg_z_act_query.8 b/doc/sg_z_act_query.8
index 6b816835..7cda1e2c 100644
--- a/doc/sg_z_act_query.8
+++ b/doc/sg_z_act_query.8
@@ -109,7 +109,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2021 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_zone,sg_rep_zones,sg_reset_wp(sg3_utils)
diff --git a/doc/sg_zone.8 b/doc/sg_zone.8
index 6c39dea2..256009ef 100644
--- a/doc/sg_zone.8
+++ b/doc/sg_zone.8
@@ -91,7 +91,7 @@ Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
Copyright \(co 2014\-2022 Douglas Gilbert
.br
-This software is distributed under a FreeBSD license. There is NO
+This software is distributed under a BSD\-2\-Clause license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
.B sg_rem_rest_elem,sg_rep_zones,sg_reset_wp,sg_z_act_query(sg3_utils)
diff --git a/include/sg_lib.h b/include/sg_lib.h
index 0fa4693a..8e2f541d 100644
--- a/include/sg_lib.h
+++ b/include/sg_lib.h
@@ -640,9 +640,9 @@ void dStrHexFp(const char* str, int len, int no_ascii, FILE * fp);
* ('.' for non printable chars) to right of each line; 1 don't (so just
* output ASCII hex). If 'oformat' is 2 output same as 1 but any LFs are
* replaced by space (and trailing spaces are trimmed). Note that an address
- * is not printed on each line preceding the hex data. Returns number of bytes
- * written to 'b' excluding the trailing '\0'. The only difference between
- * dStrHexStr() and hex2str() is the type of the first argument. */
+ * is _not_ printed on each line preceding the hex data. Returns number of
+ * bytes written to 'b' excluding the trailing '\0'. The only difference
+ * between dStrHexStr() and hex2str() is the type of the first argument. */
int dStrHexStr(const char * str, int len, const char * leadin, int oformat,
int cb_len, char * cbp);
int hex2str(const uint8_t * b_str, int len, const char * leadin, int oformat,
diff --git a/include/sg_pr2serr.h b/include/sg_pr2serr.h
index 23cad944..23295a50 100644
--- a/include/sg_pr2serr.h
+++ b/include/sg_pr2serr.h
@@ -69,10 +69,10 @@ typedef struct sgj_state_t {
/* the following set by default, the SG3_UTILS_JSON_OPTS envirinment
* variable or command line argument to --json option, in that order. */
bool pr_as_json; /* = false */
- bool pr_ane; /* 'a' abbreviated name expansion (def: false) */
bool pr_exit_status; /* 'e' (def: true) */
bool pr_hex; /* 'h' (def: false) */
bool pr_leadin; /* 'l' (def: true) */
+ bool pr_name_ex; /* 'n' name extra (information) (def: false) */
bool pr_out_hr; /* 'o' (def: false) */
bool pr_packed; /* 'k' (def: false) only when !pr_pretty */
bool pr_pretty; /* 'p' (def: true) */
@@ -87,6 +87,16 @@ typedef struct sgj_state_t {
sgj_opaque_p userp; /* for temporary usage */
} sgj_state;
+/* This function tries to convert the in_name C string to the "snake_case"
+ * convention so the output sname only contains lower case ASCII letters,
+ * numerals and "_" as a separator. Any leading or trailing underscores
+ * are removed as are repeated underscores (e.g. "_Snake __ case" becomes
+ * "snake_case"). Parentheses and the characters between them are removed.
+ * Returns sname (i.e. the pointer to the output buffer).
+ * Note: strlen(in_name) should be <= max_sname_len . */
+char * sgj_convert_to_snake_name(const char * in_name, char * sname,
+ int max_sname_len);
+
/* If jsp in non-NULL and jsp->pr_as_json is true then this call is ignored
* unless jsp->pr_out_hrp is true. Otherwise this function prints to stdout
* like printf(fmt, ...); note that no LF is added. In the jsp->pr_out_hrp is
@@ -214,6 +224,12 @@ void sgj_pr_hr_js_vs(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
void sgj_pr_hr_js_vi(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
const char * name, enum sgj_separator_t sep,
int64_t value);
+void sgj_pr_hr_js_vi_nex(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
+ const char * name, enum sgj_separator_t sep,
+ int64_t value, const char * nex_s);
+sgj_opaque_p sgj_pr_hr_js_subo(sgj_state * jsp, sgj_opaque_p jop,
+ int leadin_sp, const char * name,
+ enum sgj_separator_t sep, int64_t value);
/* Similar to sgj_pr_hr_js_vs()'s description with 'JSON string object'
* replaced by 'JSON boolean object'. */
@@ -248,21 +264,26 @@ void sgj_add_nv_ihexstr(sgj_state * jsp, sgj_opaque_p jop,
/* This function only produces JSON output if jsp is non-NULL and
* jsp->pr_as_json is true. It adds a named object at 'jop' (or jop->basep
- * if jop is NULL) along with a value. If jsp->pr_ane is true then that
+ * if jop is NULL) along with a value. If jsp->pr_name_ex is true then that
* value is two sub-objects, one named 'i' with a 'val_i' as a JSON integer,
- * the other one named "abbreviated_name_expansion" with value ane_s rendered
+ * the other one named "abbreviated_name_expansion" with value nex_s rendered
* as a JSON string. If jsp->pr_hex and 'want_hex' are true, then a
* sub-object named 'hex' with a value rendered as a hex string equal to
- * val_i. If jsp->pr_ane is false and either jsp->pr_hex or want_hex are
+ * val_i. If jsp->pr_name_ex is false and either jsp->pr_hex or want_hex are
* false then there are no sub-objects and the 'val_i' is rendered as a JSON
* integer. */
-void sgj_add_nv_ihex_ane(sgj_state * jsp, sgj_opaque_p jop, const char * name,
- int64_t val_i, bool want_hex, const char * ane_s);
+void sgj_add_nv_ihex_nex(sgj_state * jsp, sgj_opaque_p jop, const char * name,
+ int64_t val_i, bool want_hex, const char * nex_s);
-void sgj_add_nv_ihexstr_ane(sgj_state * jsp, sgj_opaque_p jop,
+void sgj_add_nv_ihexstr_nex(sgj_state * jsp, sgj_opaque_p jop,
const char * name, int64_t val_i, bool want_hex,
const char * str_name, const char * val_s,
- const char * ane_s);
+ const char * nex_s);
+
+/* Add hex byte strings irrespective of jsp->pr_hex setting. */
+void
+sgj_add_nv_hex_bytes(sgj_state * jsp, sgj_opaque_p jop, const char * name,
+ const uint8_t * byte_arr, int num_bytes);
/* Breaks up the string pointed to by 'sp' into lines and adds them to the
* jsp->out_hrp array. Treat '\n' in sp as line breaks. Consumes characters
@@ -274,11 +295,11 @@ void sgj_pr_str_out_hr(sgj_state * jsp, const char * sp, int slen);
* jsp->pr_as_json is true. 'sbp' is assumed to point to sense data as
* defined by T10 with a length of 'sb_len' bytes. Returns false if an
* issue is detetected, else it returns true. */
-bool sgj_get_sense(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * sbp,
- int sb_len);
+bool sgj_pr_js_sense(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * sbp,
+ int sb_len);
-bool sgj_get_designation_descriptor(sgj_state * jsp, sgj_opaque_p jop,
- const uint8_t * ddp, int dd_len);
+bool sgj_pr_js_designation_descriptor(sgj_state * jsp, sgj_opaque_p jop,
+ const uint8_t * ddp, int dd_len);
/* Nothing in the in-core JSON tree is actually printed to 'fp' (typically
* stdout) until this call is made. If jsp is NULL, jsp->pr_as_json is false
diff --git a/lib/sg_pr2serr.c b/lib/sg_pr2serr.c
index 310ea78b..a7bdeaf2 100644
--- a/lib/sg_pr2serr.c
+++ b/lib/sg_pr2serr.c
@@ -106,9 +106,6 @@ sgj_parse_opts(sgj_state * jsp, const char * j_optarg)
case '8':
jsp->pr_indent_size = 8;
break;
- case 'a': /* abbreviated name expansion */
- jsp->pr_ane = ! prev_negate;
- break;
case 'e':
jsp->pr_exit_status = ! prev_negate;
break;
@@ -124,6 +121,9 @@ sgj_parse_opts(sgj_state * jsp, const char * j_optarg)
case 'l':
jsp->pr_leadin = ! prev_negate;
break;
+ case 'n':
+ jsp->pr_name_ex = ! prev_negate;
+ break;
case 'o':
jsp->pr_out_hr = ! prev_negate;
break;
@@ -176,9 +176,6 @@ sg_json_usage(int char_if_not_j, char * b, int blen)
if (n >= (blen - 1))
goto fini;
n += sg_scnpr(b + n, blen - n,
- " a show 'abbreviated_name_expansion' "
- "fields\n");
- n += sg_scnpr(b + n, blen - n,
" e show 'exit_status' field\n");
n += sg_scnpr(b + n, blen - n,
" h show 'hex' fields\n");
@@ -188,6 +185,8 @@ sg_json_usage(int char_if_not_j, char * b, int blen)
" l show lead-in fields (invocation "
"information)\n");
n += sg_scnpr(b + n, blen - n,
+ " n show 'name_extra' information fields\n");
+ n += sg_scnpr(b + n, blen - n,
" o non-JSON output placed in 'output' array in "
"lead-in\n");
if (n >= (blen - 1))
@@ -219,10 +218,10 @@ fini:
char *
sg_json_settings(sgj_state * jsp, char * b, int blen)
{
- snprintf(b, blen, "%d%sa%se%sh%sk%sl%so%sp%ss%sv", jsp->pr_indent_size,
- jsp->pr_ane ? "" : "-", jsp->pr_exit_status ? "" : "-",
- jsp->pr_hex ? "" : "-", jsp->pr_packed ? "" : "-",
- jsp->pr_leadin ? "" : "-", jsp->pr_out_hr ? "" : "-",
+ snprintf(b, blen, "%d%se%sh%sk%sl%sn%so%sp%ss%sv", jsp->pr_indent_size,
+ jsp->pr_exit_status ? "" : "-", jsp->pr_hex ? "" : "-",
+ jsp->pr_packed ? "" : "-", jsp->pr_leadin ? "" : "-",
+ jsp->pr_name_ex ? "" : "-", jsp->pr_out_hr ? "" : "-",
jsp->pr_pretty ? "" : "-", jsp->pr_string ? "" : "-",
jsp->verbose ? "" : "-");
return b;
@@ -232,11 +231,11 @@ static void
sgj_def_opts(sgj_state * jsp)
{
jsp->pr_as_json = true;
- jsp->pr_ane = false;
jsp->pr_exit_status = true;
jsp->pr_hex = false;
jsp->pr_leadin = true;
jsp->pr_out_hr = false;
+ jsp->pr_name_ex = false;
jsp->pr_packed = false; /* 'k' control character, needs '-p' */
jsp->pr_pretty = true;
jsp->pr_string = true;
@@ -668,18 +667,18 @@ sgj_add_nv_ihexstr(sgj_state * jsp, sgj_opaque_p jop, const char * name,
}
}
-static const char * sc_ane_s = "abbreviated_name_expansion";
+static const char * sc_nex_s = "name_extra";
void
-sgj_add_nv_ihex_ane(sgj_state * jsp, sgj_opaque_p jop, const char * name,
- int64_t val_i, bool want_hex, const char * ane_s)
+sgj_add_nv_ihex_nex(sgj_state * jsp, sgj_opaque_p jop, const char * name,
+ int64_t val_i, bool want_hex, const char * nex_s)
{
bool as_hex = jsp->pr_hex && want_hex;
- bool as_ane = jsp->pr_ane && ane_s;
+ bool as_nex = jsp->pr_name_ex && nex_s;
if ((NULL == jsp) || (! jsp->pr_as_json))
return;
- if (! (as_hex || as_ane))
+ if (! (as_hex || as_nex))
sgj_add_nv_i(jsp, jop, name, val_i);
else {
char b[64];
@@ -689,12 +688,12 @@ sgj_add_nv_ihex_ane(sgj_state * jsp, sgj_opaque_p jop, const char * name,
if (NULL == jo2p)
return;
sgj_add_nv_i(jsp, jo2p, "i", (int64_t)val_i);
- if (as_ane) {
+ if (as_nex) {
if (jsp->pr_hex && want_hex) {
snprintf(b, sizeof(b), "%" PRIx64, val_i);
sgj_add_nv_s(jsp, jo2p, "hex", b);
}
- sgj_add_nv_s(jsp, jo2p, sc_ane_s, ane_s);
+ sgj_add_nv_s(jsp, jo2p, sc_nex_s, nex_s);
} else if (as_hex) {
snprintf(b, sizeof(b), "%" PRIx64, val_i);
sgj_add_nv_s(jsp, jo2p, "hex", b);
@@ -721,18 +720,18 @@ sgj_add_nv_hex_bytes(sgj_state * jsp, sgj_opaque_p jop, const char * name,
}
void
-sgj_add_nv_ihexstr_ane(sgj_state * jsp, sgj_opaque_p jop, const char * name,
+sgj_add_nv_ihexstr_nex(sgj_state * jsp, sgj_opaque_p jop, const char * name,
int64_t val_i, bool want_hex, const char * str_name,
- const char * val_s, const char * ane_s)
+ const char * val_s, const char * nex_s)
{
bool as_hex = jsp->pr_hex && want_hex;
bool as_str = jsp->pr_string && val_s;
- bool as_ane = jsp->pr_ane && ane_s;
+ bool as_nex = jsp->pr_name_ex && nex_s;
const char * sname = str_name ? str_name : sc_mn_s;
if ((NULL == jsp) || (! jsp->pr_as_json))
return;
- if (! (as_hex || as_ane || as_str))
+ if (! (as_hex || as_nex || as_str))
sgj_add_nv_i(jsp, jop, name, val_i);
else {
char b[64];
@@ -742,7 +741,7 @@ sgj_add_nv_ihexstr_ane(sgj_state * jsp, sgj_opaque_p jop, const char * name,
if (NULL == jo2p)
return;
sgj_add_nv_i(jsp, jo2p, "i", (int64_t)val_i);
- if (as_ane) {
+ if (as_nex) {
if (as_hex) {
snprintf(b, sizeof(b), "%" PRIx64, val_i);
sgj_add_nv_s(jsp, jo2p, "hex", b);
@@ -750,7 +749,7 @@ sgj_add_nv_ihexstr_ane(sgj_state * jsp, sgj_opaque_p jop, const char * name,
if (as_str) {
sgj_add_nv_s(jsp, jo2p, sname, val_s);
}
- sgj_add_nv_s(jsp, jo2p, sc_ane_s, ane_s);
+ sgj_add_nv_s(jsp, jo2p, sc_nex_s, nex_s);
} else if (as_hex) {
snprintf(b, sizeof(b), "%" PRIx64, val_i);
sgj_add_nv_s(jsp, jo2p, "hex", b);
@@ -792,16 +791,26 @@ sgj_pr_str_out_hr(sgj_state * jsp, const char * sp, int slen)
}
}
+char *
+sgj_convert_to_snake_name(const char * in_name, char * sname,
+ int max_sname_len)
+{
+ sgj_name_to_snake(in_name, sname, max_sname_len);
+ return sname;
+}
+
/* This function tries to convert the 'in' C string to "snake_case"
* convention so the output 'out' only contains lower case ASCII letters,
* numerals and "_" as a separator. Any leading or trailing underscores
* are removed as are repeated underscores (e.g. "_Snake __ case" becomes
- * "snake_case"). Returns number of characters placed in 'out' excluding
- * the trailing NULL */
+ * "snake_case"). Parentheses and the characters between them are removed.
+ * Returns number of characters placed in 'out' excluding the trailing
+ * NULL */
static int
sgj_name_to_snake(const char * in, char * out, int maxlen_out)
{
bool prev_underscore = false;
+ bool within_paren = false;
int c, k, j, inlen;
if (maxlen_out < 2) {
@@ -812,10 +821,17 @@ sgj_name_to_snake(const char * in, char * out, int maxlen_out)
inlen = strlen(in);
for (k = 0, j = 0; (k < inlen) && (j < maxlen_out); ++k) {
c = in[k];
+ if (within_paren) {
+ if (')' == c)
+ within_paren = false;
+ continue;
+ }
if (isalnum(c)) {
out[j++] = isupper(c) ? tolower(c) : c;
prev_underscore = false;
- } else if ((j > 0) && (! prev_underscore)) {
+ } else if ('(' == c)
+ within_paren = true;
+ else if ((j > 0) && (! prev_underscore)) {
out[j++] = '_';
prev_underscore = true;
}
@@ -836,12 +852,82 @@ sgj_name_to_snake(const char * in, char * out, int maxlen_out)
return k;
}
+static int
+sgj_jtype_to_s(char * b, int blen_max, json_value * jvp)
+{
+ json_type jtype = jvp ? jvp->type : json_none;
+
+ switch (jtype) {
+ case json_string:
+ return sg_scnpr(b, blen_max, "%s", jvp->u.string.ptr);
+ case json_integer:
+ return sg_scnpr(b, blen_max, "%" PRIi64, jvp->u.integer);
+ case json_boolean:
+ return sg_scnpr(b, blen_max, "%s", jvp->u.boolean ? "true" : "false");
+ case json_none:
+ default:
+ if ((blen_max > 0) && ('\0' != b[0]))
+ b[0] = '\0';
+ break;
+ }
+ return 0;
+}
+
+static int
+sgj_pr_hr_js_hr(char * b, int blen_max, const char * name,
+ enum sgj_separator_t sep, bool use_jvp,
+ json_value * jvp, int64_t val_instead)
+{
+ int n = 0;
+
+ if (name) {
+ n += sg_scnpr(b + n, blen_max - n, "%s", name);
+ switch (sep) {
+ case SGJ_SEP_NONE:
+ break;
+ case SGJ_SEP_SPACE_1:
+ n += sg_scnpr(b + n, blen_max - n, " ");
+ break;
+ case SGJ_SEP_SPACE_2:
+ n += sg_scnpr(b + n, blen_max - n, " ");
+ break;
+ case SGJ_SEP_SPACE_3:
+ n += sg_scnpr(b + n, blen_max - n, " ");
+ break;
+ case SGJ_SEP_SPACE_4:
+ n += sg_scnpr(b + n, blen_max - n, " ");
+ break;
+ case SGJ_SEP_EQUAL_NO_SPACE:
+ n += sg_scnpr(b + n, blen_max - n, "=");
+ break;
+ case SGJ_SEP_EQUAL_1_SPACE:
+ n += sg_scnpr(b + n, blen_max - n, "= ");
+ break;
+ case SGJ_SEP_COLON_NO_SPACE:
+ n += sg_scnpr(b + n, blen_max - n, ":");
+ break;
+ case SGJ_SEP_COLON_1_SPACE:
+ n += sg_scnpr(b + n, blen_max - n, ": ");
+ break;
+ default:
+ break;
+ }
+ }
+ if (use_jvp)
+ n += sgj_jtype_to_s(b + n, blen_max - n, jvp);
+ else
+ n += sg_scnpr(b + n, blen_max - n, "%" PRIi64, val_instead);
+ return n;
+}
+
static void
sgj_pr_hr_js_xx(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
- const char * name, enum sgj_separator_t sep, json_value * jvp)
+ const char * name, enum sgj_separator_t sep,
+ json_value * jvp, const char * nex_s)
{
bool eaten = false;
bool as_json = (jsp && jsp->pr_as_json);
+ bool done;
int n;
json_type jtype = jvp ? jvp->type : json_none;
char b[256];
@@ -855,21 +941,7 @@ sgj_pr_hr_js_xx(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
b[n] = '\0';
if (NULL == name) {
if ((! as_json) || (jsp && jsp->pr_out_hr)) {
- switch (jtype) {
- case json_string:
- sg_scnpr(b + n, blen - n, "%s", jvp->u.string.ptr);
- break;
- case json_integer:
- sg_scnpr(b + n, blen - n, "%" PRIi64, jvp->u.integer);
- break;
- case json_boolean:
- sg_scnpr(b + n, blen - n, "%s",
- jvp->u.boolean ? "true" : "false");
- break;
- case json_none:
- default:
- break;
- }
+ n += sgj_jtype_to_s(b + n, blen - n, jvp);
printf("%s\n", b);
}
if (NULL == jop) {
@@ -885,11 +957,8 @@ sgj_pr_hr_js_xx(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
jvp ? jvp : json_null_new());
}
}
- if (jvp && (! eaten))
- json_builder_free((json_value *)jvp);
- return;
+ goto fini;
}
- n += sg_scnpr(b + n, blen - n, "%s", name);
if (as_json) {
int k;
@@ -897,61 +966,41 @@ sgj_pr_hr_js_xx(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
jop = jsp->basep;
k = sgj_name_to_snake(name, jname, sizeof(jname));
if (k > 0) {
- eaten = true;
- json_object_push((json_value *)jop, jname,
- jvp ? jvp : json_null_new());
- }
- }
- if (jvp && ((as_json && jsp->pr_out_hr) || (! as_json))) {
- switch (sep) {
- case SGJ_SEP_NONE:
- break;
- case SGJ_SEP_SPACE_1:
- n += sg_scnpr(b + n, blen - n, " ");
- break;
- case SGJ_SEP_SPACE_2:
- n += sg_scnpr(b + n, blen - n, " ");
- break;
- case SGJ_SEP_SPACE_3:
- n += sg_scnpr(b + n, blen - n, " ");
- break;
- case SGJ_SEP_SPACE_4:
- n += sg_scnpr(b + n, blen - n, " ");
- break;
- case SGJ_SEP_EQUAL_NO_SPACE:
- n += sg_scnpr(b + n, blen - n, "=");
- break;
- case SGJ_SEP_EQUAL_1_SPACE:
- n += sg_scnpr(b + n, blen - n, "= ");
- break;
- case SGJ_SEP_COLON_NO_SPACE:
- n += sg_scnpr(b + n, blen - n, ":");
- break;
- case SGJ_SEP_COLON_1_SPACE:
- n += sg_scnpr(b + n, blen - n, ": ");
- break;
- default:
- break;
- }
- switch (jtype) {
- case json_string:
- sg_scnpr(b + n, blen - n, "%s", jvp->u.string.ptr);
- break;
- case json_integer:
- sg_scnpr(b + n, blen - n, "%" PRIi64, jvp->u.integer);
- break;
- case json_boolean:
- sg_scnpr(b + n, blen - n, "%s", jvp->u.boolean ? "true" : "false");
- break;
- case json_none:
- default:
- break;
+ done = false;
+ if (nex_s && (strlen(nex_s) > 0)) {
+ switch (jtype) {
+ case json_string:
+ break;
+ case json_integer:
+ sgj_add_nv_ihex_nex(jsp, jop, jname, jvp->u.integer,
+ false, nex_s);
+ done = true;
+ break;
+ case json_boolean:
+ sgj_add_nv_ihex_nex(jsp, jop, jname, jvp->u.boolean,
+ false, nex_s);
+ done = true;
+ break;
+ case json_none:
+ default:
+ break;
+ }
+ }
+ if (! done) {
+ eaten = true;
+ json_object_push((json_value *)jop, jname,
+ jvp ? jvp : json_null_new());
+ }
}
}
+ if (jvp && ((as_json && jsp->pr_out_hr) || (! as_json)))
+ n += sgj_pr_hr_js_hr(b + n, blen - n, name, sep, true, jvp, 0);
+
if (as_json && jsp->pr_out_hr)
json_array_push((json_value *)jsp->out_hrp, json_string_new(b));
- else if (! as_json)
+ if (! as_json)
printf("%s\n", b);
+fini:
if (jvp && (! eaten))
json_builder_free((json_value *)jvp);
}
@@ -965,7 +1014,7 @@ sgj_pr_hr_js_vs(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
/* make json_value even if jsp->pr_as_json is false */
jvp = value ? json_string_new(value) : NULL;
- sgj_pr_hr_js_xx(jsp, jop, leadin_sp, name, sep, jvp);
+ sgj_pr_hr_js_xx(jsp, jop, leadin_sp, name, sep, jvp, NULL);
}
void
@@ -975,7 +1024,18 @@ sgj_pr_hr_js_vi(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
json_value * jvp;
jvp = json_integer_new(value);
- sgj_pr_hr_js_xx(jsp, jop, leadin_sp, name, sep, jvp);
+ sgj_pr_hr_js_xx(jsp, jop, leadin_sp, name, sep, jvp, NULL);
+}
+
+void
+sgj_pr_hr_js_vi_nex(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
+ const char * name, enum sgj_separator_t sep,
+ int64_t value, const char * nex_s)
+{
+ json_value * jvp;
+
+ jvp = json_integer_new(value);
+ sgj_pr_hr_js_xx(jsp, jop, leadin_sp, name, sep, jvp, nex_s);
}
void
@@ -985,7 +1045,40 @@ sgj_pr_hr_js_vb(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
json_value * jvp;
jvp = json_boolean_new(value);
- sgj_pr_hr_js_xx(jsp, jop, leadin_sp, name, sep, jvp);
+ sgj_pr_hr_js_xx(jsp, jop, leadin_sp, name, sep, jvp, NULL);
+}
+
+sgj_opaque_p
+sgj_pr_hr_js_subo(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
+ const char * name, enum sgj_separator_t sep, int64_t value)
+{
+ bool as_json = (jsp && jsp->pr_as_json);
+ int n = 0;
+ sgj_opaque_p jo2p;
+ char b[256];
+ static const int blen = sizeof(b);
+
+ if (NULL == name)
+ return NULL;
+ for (n = 0; n < leadin_sp; ++n)
+ b[n] = ' ';
+ b[n] = '\0';
+ if ((! as_json) || (jsp && jsp->pr_out_hr))
+ n += sgj_pr_hr_js_hr(b + n, blen - n, name, sep, false, NULL, value);
+
+ if (as_json && jsp->pr_out_hr)
+ json_array_push((json_value *)jsp->out_hrp, json_string_new(b));
+ if (! as_json)
+ printf("%s\n", b);
+
+ if (as_json) {
+ sgj_name_to_snake(name, b, blen);
+ jo2p = sgj_new_named_object(jsp, jop, b);
+ if (jo2p)
+ sgj_add_nv_i(jsp, jo2p, "i", value);
+ return jo2p;
+ }
+ return NULL;
}
#ifdef SG_PRSE_SENSE_DECODE
@@ -997,8 +1090,8 @@ static const char * naa_exp = "Network Address Authority";
static const char * aoi_exp = "IEEE-Administered Organizational Identifier";
bool
-sgj_get_designation_descriptor(sgj_state * jsp, sgj_opaque_p jop,
- const uint8_t * ddp, int dd_len)
+sgj_pr_js_designation_descriptor(sgj_state * jsp, sgj_opaque_p jop,
+ const uint8_t * ddp, int dd_len)
{
int p_id, piv, c_set, assoc, desig_type, d_id, naa;
int n, aoi, vsi, dlen;
@@ -1043,7 +1136,7 @@ sgj_get_designation_descriptor(sgj_state * jsp, sgj_opaque_p jop,
cp = "unknown";
sgj_add_nv_ihexstr(jsp, jop, "code_set", desig_type,
NULL, cp);
- sgj_add_nv_ihex_ane(jsp, jop, "piv", piv, false,
+ sgj_add_nv_ihex_nex(jsp, jop, "piv", piv, false,
"Protocol Identifier Valid");
sg_get_trans_proto_str(p_id, elen, e);
sgj_add_nv_ihexstr(jsp, jop, "protocol_identifier", p_id, NULL, e);
@@ -1089,37 +1182,37 @@ sgj_get_designation_descriptor(sgj_state * jsp, sgj_opaque_p jop,
switch (naa) {
case 2:
naa_sp = "IEEE Extended";
- sgj_add_nv_ihexstr_ane(jsp, jop, "naa", naa, false, NULL, naa_sp,
+ sgj_add_nv_ihexstr_nex(jsp, jop, "naa", naa, false, NULL, naa_sp,
naa_exp);
d_id = (((ip[0] & 0xf) << 8) | ip[1]);
sgj_add_nv_ihex(jsp, jop, "vendor_specific_identifier_a", d_id);
aoi = sg_get_unaligned_be24(ip + 2);
- sgj_add_nv_ihex_ane(jsp, jop, "aoi", aoi, true, aoi_exp);
+ sgj_add_nv_ihex_nex(jsp, jop, "aoi", aoi, true, aoi_exp);
vsi = sg_get_unaligned_be24(ip + 5);
sgj_add_nv_ihex(jsp, jop, "vendor_specific_identifier_b", vsi);
break;
case 3:
naa_sp = "Locally Assigned";
- sgj_add_nv_ihexstr_ane(jsp, jop, "naa", naa, false, NULL, naa_sp,
+ sgj_add_nv_ihexstr_nex(jsp, jop, "naa", naa, false, NULL, naa_sp,
naa_exp);
ull = sg_get_unaligned_be64(ip + 0) & 0xfffffffffffffffULL;
sgj_add_nv_ihex(jsp, jop, "locally_administered_value", ull);
break;
case 5:
naa_sp = "IEEE Registered";
- sgj_add_nv_ihexstr_ane(jsp, jop, "naa", naa, false, NULL, naa_sp,
+ sgj_add_nv_ihexstr_nex(jsp, jop, "naa", naa, false, NULL, naa_sp,
naa_exp);
aoi = (sg_get_unaligned_be32(ip + 0) >> 4) & 0xffffff;
- sgj_add_nv_ihex_ane(jsp, jop, "aoi", aoi, true, aoi_exp);
+ sgj_add_nv_ihex_nex(jsp, jop, "aoi", aoi, true, aoi_exp);
ull = sg_get_unaligned_be48(ip + 2) & 0xfffffffffULL;
sgj_add_nv_ihex(jsp, jop, "vendor_specific_identifier", ull);
break;
case 6:
naa_sp = "IEEE Registered Extended";
- sgj_add_nv_ihexstr_ane(jsp, jop, "naa", naa, false, NULL, naa_sp,
+ sgj_add_nv_ihexstr_nex(jsp, jop, "naa", naa, false, NULL, naa_sp,
naa_exp);
aoi = (sg_get_unaligned_be32(ip + 0) >> 4) & 0xffffff;
- sgj_add_nv_ihex_ane(jsp, jop, "aoi", aoi, true, aoi_exp);
+ sgj_add_nv_ihex_nex(jsp, jop, "aoi", aoi, true, aoi_exp);
ull = sg_get_unaligned_be48(ip + 2) & 0xfffffffffULL;
sgj_add_nv_ihex(jsp, jop, "vendor_specific_identifier", ull);
ull = sg_get_unaligned_be64(ip + 8);
@@ -1128,7 +1221,7 @@ sgj_get_designation_descriptor(sgj_state * jsp, sgj_opaque_p jop,
break;
default:
snprintf(b, blen, "unknown NAA value=0x%x", naa);
- sgj_add_nv_ihexstr_ane(jsp, jop, "naa", naa, true, NULL, b,
+ sgj_add_nv_ihexstr_nex(jsp, jop, "naa", naa, true, NULL, b,
naa_exp);
sgj_add_nv_hex_bytes(jsp, jop, "full_naa_hexbytes", ip, dlen);
break;
@@ -1238,11 +1331,11 @@ sgj_decode_sks(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * dp, int dlen,
sgj_add_nv_s(jsp, jop, "illegal_request_sks", dtsp);
return false;
}
- sgj_add_nv_ihex_ane(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
+ sgj_add_nv_ihex_nex(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
sksvp);
- sgj_add_nv_ihex_ane(jsp, jop, "c_d", !! (dp[0] & 0x40), false,
+ sgj_add_nv_ihex_nex(jsp, jop, "c_d", !! (dp[0] & 0x40), false,
"c: cdb; d: data-out");
- sgj_add_nv_ihex_ane(jsp, jop, "bpv", !! (dp[0] & 0x8), false,
+ sgj_add_nv_ihex_nex(jsp, jop, "bpv", !! (dp[0] & 0x8), false,
"bit pointer (index) valid");
sgj_add_nv_i(jsp, jop, "bit_pointer", dp[0] & 0x7);
sgj_add_nv_ihex(jsp, jop, "field_pointer",
@@ -1255,7 +1348,7 @@ sgj_decode_sks(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * dp, int dlen,
sgj_add_nv_s(jsp, jop, "actual_retry_count_sks", dtsp);
return false;
}
- sgj_add_nv_ihex_ane(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
+ sgj_add_nv_ihex_nex(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
sksvp);
sgj_add_nv_ihex(jsp, jop, "actual_retry_count",
sg_get_unaligned_be16(dp + 1));
@@ -1266,7 +1359,7 @@ sgj_decode_sks(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * dp, int dlen,
sgj_add_nv_s(jsp, jop, "progress_indication_sks", dtsp);
return false;
}
- sgj_add_nv_ihex_ane(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
+ sgj_add_nv_ihex_nex(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
sksvp);
sgj_progress_indication(jsp, jop, sg_get_unaligned_be16(dp + 1),
false);
@@ -1276,12 +1369,12 @@ sgj_decode_sks(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * dp, int dlen,
sgj_add_nv_s(jsp, jop, "segment_indication_sks", dtsp);
return false;
}
- sgj_add_nv_ihex_ane(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
+ sgj_add_nv_ihex_nex(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
sksvp);
- sgj_add_nv_ihex_ane(jsp, jop, "sd", !! (dp[0] & 0x20), false,
+ sgj_add_nv_ihex_nex(jsp, jop, "sd", !! (dp[0] & 0x20), false,
"field pointer relative to: 1->segment "
"descriptor, 0->parameter list");
- sgj_add_nv_ihex_ane(jsp, jop, "bpv", !! (dp[0] & 0x8), false,
+ sgj_add_nv_ihex_nex(jsp, jop, "bpv", !! (dp[0] & 0x8), false,
"bit pointer (index) valid");
sgj_add_nv_i(jsp, jop, "bit_pointer", dp[0] & 0x7);
sgj_add_nv_ihex(jsp, jop, "field_pointer",
@@ -1292,7 +1385,7 @@ sgj_decode_sks(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * dp, int dlen,
sgj_add_nv_s(jsp, jop, "segment_indication_sks", dtsp);
return false;
}
- sgj_add_nv_ihex_ane(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
+ sgj_add_nv_ihex_nex(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
sksvp);
sgj_add_nv_i(jsp, jop, "overflow", !! (dp[0] & 0x80));
break;
@@ -1342,7 +1435,7 @@ sgj_uds_referral_descriptor(sgj_state * jsp, sgj_opaque_p jop,
sgj_opaque_p jap, jo2p, ja2p, jo3p;
char c[40];
- sgj_add_nv_ihex_ane(jsp, jop, "not_all_r", (dp[2] & 0x1), false,
+ sgj_add_nv_ihex_nex(jsp, jop, "not_all_r", (dp[2] & 0x1), false,
"Not all referrals");
dp += 4;
jap = sgj_new_named_array(jsp, jop,
@@ -1391,9 +1484,9 @@ static const char * dd_usage_reason_str_arr[] = {
};
static bool
-sgj_get_sense_descriptors(sgj_state * jsp, sgj_opaque_p jop,
- const struct sg_scsi_sense_hdr * sshp,
- const uint8_t * sbp, int sb_len)
+sgj_pr_js_sense_descriptors(sgj_state * jsp, sgj_opaque_p jop,
+ const struct sg_scsi_sense_hdr * sshp,
+ const uint8_t * sbp, int sb_len)
{
bool processed = true;
int add_sb_len, desc_len, k, dt, sense_key, n, sds;
@@ -1473,9 +1566,9 @@ sgj_get_sense_descriptors(sgj_state * jsp, sgj_opaque_p jop,
"Stream commands");
if (add_d_len >= 2) {
sgj_add_nv_i(jsp, jo2p, "filemark", !! (descp[3] & 0x80));
- sgj_add_nv_ihex_ane(jsp, jo2p, "eom", !! (descp[3] & 0x40),
+ sgj_add_nv_ihex_nex(jsp, jo2p, "eom", !! (descp[3] & 0x40),
false, "End Of Medium");
- sgj_add_nv_ihex_ane(jsp, jo2p, "ili", !! (descp[3] & 0x20),
+ sgj_add_nv_ihex_nex(jsp, jo2p, "ili", !! (descp[3] & 0x20),
false, "Incorrect Length Indicator");
} else {
sgj_add_nv_s(jsp, jo2p, parsing, dtsp);
@@ -1486,7 +1579,7 @@ sgj_get_sense_descriptors(sgj_state * jsp, sgj_opaque_p jop,
sgj_add_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
"Block commands");
if (add_d_len >= 2)
- sgj_add_nv_ihex_ane(jsp, jo2p, "ili", !! (descp[3] & 0x20),
+ sgj_add_nv_ihex_nex(jsp, jo2p, "ili", !! (descp[3] & 0x20),
false, "Incorrect Length Indicator");
else {
sgj_add_nv_s(jsp, jo2p, parsing, dtsp);
@@ -1571,7 +1664,7 @@ sgj_get_sense_descriptors(sgj_state * jsp, sgj_opaque_p jop,
processed = false;
break;
}
- sgj_add_nv_ihex_ane(jsp, jo2p, "fsdt", !! (0x80 & descp[2]),
+ sgj_add_nv_ihex_nex(jsp, jo2p, "fsdt", !! (0x80 & descp[2]),
false, "Forwarded Sense Data Truncated");
sds = (0x7 & descp[2]);
if (sds < 1)
@@ -1588,7 +1681,7 @@ sgj_get_sense_descriptors(sgj_state * jsp, sgj_opaque_p jop,
sgj_add_nv_ihexstr(jsp, jo2p, "sense_data_source",
(0x7 & descp[2]), NULL, b);
jo3p = sgj_new_named_object(jsp, jo2p, "forwarded_sense_data");
- sgj_get_sense(jsp, jo3p, descp + 4, desc_len - 4);
+ sgj_pr_js_sense(jsp, jo3p, descp + 4, desc_len - 4);
break;
case 0xd: /* Added in SBC-3 rev 36d */
/* this descriptor combines descriptors 0, 1, 2 and 3 */
@@ -1600,7 +1693,7 @@ sgj_get_sense_descriptors(sgj_state * jsp, sgj_opaque_p jop,
break;
}
sgj_add_nv_i(jsp, jo2p, "valid", (0x80 & descp[2]));
- sgj_add_nv_ihex_ane(jsp, jo2p, "ili", !! (0x20 & descp[2]),
+ sgj_add_nv_ihex_nex(jsp, jo2p, "ili", !! (0x20 & descp[2]),
false, "Incorrect Length Indicator");
processed = sgj_decode_sks(jsp, jo2p, descp + 4, desc_len - 4,
sense_key);
@@ -1621,8 +1714,8 @@ sgj_get_sense_descriptors(sgj_state * jsp, sgj_opaque_p jop,
n, NULL, cp);
jo3p = sgj_new_named_object(jsp, jo2p,
"device_designation_descriptor");
- sgj_get_designation_descriptor(jsp, jo3p, descp + 4,
- desc_len - 4);
+ sgj_pr_js_designation_descriptor(jsp, jo3p, descp + 4,
+ desc_len - 4);
break;
case 0xf: /* Added in SPC-5 rev 10 (for Write buffer) */
sgj_add_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
@@ -1643,12 +1736,12 @@ sgj_get_sense_descriptors(sgj_state * jsp, sgj_opaque_p jop,
processed = false;
break;
}
- sgj_add_nv_ihex_ane(jsp, jo2p, "dnr", !! (0x80 & descp[5]),
+ sgj_add_nv_ihex_nex(jsp, jo2p, "dnr", !! (0x80 & descp[5]),
false, "Do not retry");
- sgj_add_nv_ihex_ane(jsp, jo2p, "m", !! (0x40 & descp[5]),
+ sgj_add_nv_ihex_nex(jsp, jo2p, "m", !! (0x40 & descp[5]),
false, "More");
sct_sc = sg_get_unaligned_be16(descp + 6);
- sgj_add_nv_ihexstr_ane
+ sgj_add_nv_ihexstr_nex
(jsp, jo2p, "sct_sc", sct_sc, true, NULL,
sg_get_nvme_cmd_status_str(sct_sc, blen, b),
"Status Code Type (upper 8 bits) and Status Code");
@@ -1673,8 +1766,8 @@ sgj_get_sense_descriptors(sgj_state * jsp, sgj_opaque_p jop,
/* Fetch sense information */
bool
-sgj_get_sense(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * sbp,
- int sb_len)
+sgj_pr_js_sense(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * sbp,
+ int sb_len)
{
bool descriptor_format = false;
bool sdat_ovfl = false;
@@ -1736,7 +1829,7 @@ sgj_get_sense(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * sbp,
}
sgj_add_nv_ihexstr(jsp, jop, "response_code", resp_code, NULL, ebp);
sgj_add_nv_b(jsp, jop, "descriptor_format", descriptor_format);
- sgj_add_nv_ihex_ane(jsp, jop, "sdat_ovfl", sdat_ovfl, false,
+ sgj_add_nv_ihex_nex(jsp, jop, "sdat_ovfl", sdat_ovfl, false,
"Sense data overflow");
sgj_add_nv_ihexstr(jsp, jop, "sense_key", ssh.sense_key, NULL,
sg_lib_sense_key_desc[ssh.sense_key]);
@@ -1747,7 +1840,8 @@ sgj_get_sense(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * sbp,
blen, b));
if (descriptor_format) {
if (len > 8) {
- ret = sgj_get_sense_descriptors(jsp, jop, &ssh, sbp + 8, len - 8);
+ ret = sgj_pr_js_sense_descriptors(jsp, jop, &ssh, sbp + 8,
+ len - 8);
if (ret == false) {
ebp = "unable to decode sense descriptor";
goto fini;
@@ -1767,9 +1861,9 @@ sgj_get_sense(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * sbp,
} else if (len > 2) { /* fixed format */
sgj_add_nv_i(jsp, jop, "valid", valid_info_fld);
sgj_add_nv_i(jsp, jop, "filemark", !! (sbp[2] & 0x80));
- sgj_add_nv_ihex_ane(jsp, jop, "eom", !! (sbp[2] & 0x40),
+ sgj_add_nv_ihex_nex(jsp, jop, "eom", !! (sbp[2] & 0x40),
false, "End Of Medium");
- sgj_add_nv_ihex_ane(jsp, jop, "ili", !! (sbp[2] & 0x20),
+ sgj_add_nv_ihex_nex(jsp, jop, "ili", !! (sbp[2] & 0x20),
false, "Incorrect Length Indicator");
info = sg_get_unaligned_be32(sbp + 3);
sgj_add_nv_ihex(jsp, jop, "information", info);
diff --git a/src/Makefile.am b/src/Makefile.am
index 034f171d..b4b6bc71 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -90,7 +90,7 @@ sg_ident_LDADD = ../lib/libsgutils2.la
sginfo_LDADD = ../lib/libsgutils2.la
-sg_inq_SOURCES = sg_inq.c sg_inq_data.c
+sg_inq_SOURCES = sg_inq.c sg_inq_data.c sg_vpd_common.c
sg_inq_LDADD = ../lib/libsgutils2.la
sg_logs_LDADD = ../lib/libsgutils2.la
@@ -190,7 +190,7 @@ sg_unmap_LDADD = ../lib/libsgutils2.la
sg_verify_LDADD = ../lib/libsgutils2.la
-sg_vpd_SOURCES = sg_vpd.c sg_vpd_vendor.c
+sg_vpd_SOURCES = sg_vpd.c sg_vpd_vendor.c sg_vpd_common.c
sg_vpd_LDADD = ../lib/libsgutils2.la
sg_wr_mode_LDADD = ../lib/libsgutils2.la
diff --git a/src/Makefile.in b/src/Makefile.in
index a71b2ca7..9fb93bf7 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -187,7 +187,8 @@ sg_get_lba_status_DEPENDENCIES = ../lib/libsgutils2.la
sg_ident_SOURCES = sg_ident.c
sg_ident_OBJECTS = sg_ident.$(OBJEXT)
sg_ident_DEPENDENCIES = ../lib/libsgutils2.la
-am_sg_inq_OBJECTS = sg_inq.$(OBJEXT) sg_inq_data.$(OBJEXT)
+am_sg_inq_OBJECTS = sg_inq.$(OBJEXT) sg_inq_data.$(OBJEXT) \
+ sg_vpd_common.$(OBJEXT)
sg_inq_OBJECTS = $(am_sg_inq_OBJECTS)
sg_inq_DEPENDENCIES = ../lib/libsgutils2.la
sg_logs_SOURCES = sg_logs.c
@@ -340,7 +341,8 @@ sg_unmap_DEPENDENCIES = ../lib/libsgutils2.la
sg_verify_SOURCES = sg_verify.c
sg_verify_OBJECTS = sg_verify.$(OBJEXT)
sg_verify_DEPENDENCIES = ../lib/libsgutils2.la
-am_sg_vpd_OBJECTS = sg_vpd.$(OBJEXT) sg_vpd_vendor.$(OBJEXT)
+am_sg_vpd_OBJECTS = sg_vpd.$(OBJEXT) sg_vpd_vendor.$(OBJEXT) \
+ sg_vpd_common.$(OBJEXT)
sg_vpd_OBJECTS = $(am_sg_vpd_OBJECTS)
sg_vpd_DEPENDENCIES = ../lib/libsgutils2.la
sg_wr_mode_SOURCES = sg_wr_mode.c
@@ -429,13 +431,13 @@ am__depfiles_remade = ./$(DEPDIR)/sg_bg_ctl.Po \
./$(DEPDIR)/sg_test_rwbuf.Po ./$(DEPDIR)/sg_timestamp.Po \
./$(DEPDIR)/sg_turs.Po ./$(DEPDIR)/sg_unmap.Po \
./$(DEPDIR)/sg_verify.Po ./$(DEPDIR)/sg_vpd.Po \
- ./$(DEPDIR)/sg_vpd_vendor.Po ./$(DEPDIR)/sg_wr_mode.Po \
- ./$(DEPDIR)/sg_write_buffer.Po ./$(DEPDIR)/sg_write_long.Po \
- ./$(DEPDIR)/sg_write_same.Po ./$(DEPDIR)/sg_write_verify.Po \
- ./$(DEPDIR)/sg_write_x.Po ./$(DEPDIR)/sg_xcopy.Po \
- ./$(DEPDIR)/sg_z_act_query.Po ./$(DEPDIR)/sg_zone.Po \
- ./$(DEPDIR)/sginfo.Po ./$(DEPDIR)/sgm_dd.Po \
- ./$(DEPDIR)/sgp_dd.Po
+ ./$(DEPDIR)/sg_vpd_common.Po ./$(DEPDIR)/sg_vpd_vendor.Po \
+ ./$(DEPDIR)/sg_wr_mode.Po ./$(DEPDIR)/sg_write_buffer.Po \
+ ./$(DEPDIR)/sg_write_long.Po ./$(DEPDIR)/sg_write_same.Po \
+ ./$(DEPDIR)/sg_write_verify.Po ./$(DEPDIR)/sg_write_x.Po \
+ ./$(DEPDIR)/sg_xcopy.Po ./$(DEPDIR)/sg_z_act_query.Po \
+ ./$(DEPDIR)/sg_zone.Po ./$(DEPDIR)/sginfo.Po \
+ ./$(DEPDIR)/sgm_dd.Po ./$(DEPDIR)/sgp_dd.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -676,7 +678,7 @@ sg_get_elem_status_LDADD = ../lib/libsgutils2.la
sg_get_lba_status_LDADD = ../lib/libsgutils2.la
sg_ident_LDADD = ../lib/libsgutils2.la
sginfo_LDADD = ../lib/libsgutils2.la
-sg_inq_SOURCES = sg_inq.c sg_inq_data.c
+sg_inq_SOURCES = sg_inq.c sg_inq_data.c sg_vpd_common.c
sg_inq_LDADD = ../lib/libsgutils2.la
sg_logs_LDADD = ../lib/libsgutils2.la
sg_luns_LDADD = ../lib/libsgutils2.la
@@ -728,7 +730,7 @@ sg_timestamp_LDADD = ../lib/libsgutils2.la
sg_turs_LDADD = ../lib/libsgutils2.la @RT_LIB@
sg_unmap_LDADD = ../lib/libsgutils2.la
sg_verify_LDADD = ../lib/libsgutils2.la
-sg_vpd_SOURCES = sg_vpd.c sg_vpd_vendor.c
+sg_vpd_SOURCES = sg_vpd.c sg_vpd_vendor.c sg_vpd_common.c
sg_vpd_LDADD = ../lib/libsgutils2.la
sg_wr_mode_LDADD = ../lib/libsgutils2.la
sg_write_buffer_LDADD = ../lib/libsgutils2.la
@@ -1183,6 +1185,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_unmap.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_verify.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_vpd.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_vpd_common.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_vpd_vendor.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_wr_mode.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_write_buffer.Po@am__quote@ # am--include-marker
@@ -1419,6 +1422,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/sg_unmap.Po
-rm -f ./$(DEPDIR)/sg_verify.Po
-rm -f ./$(DEPDIR)/sg_vpd.Po
+ -rm -f ./$(DEPDIR)/sg_vpd_common.Po
-rm -f ./$(DEPDIR)/sg_vpd_vendor.Po
-rm -f ./$(DEPDIR)/sg_wr_mode.Po
-rm -f ./$(DEPDIR)/sg_write_buffer.Po
@@ -1540,6 +1544,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/sg_unmap.Po
-rm -f ./$(DEPDIR)/sg_verify.Po
-rm -f ./$(DEPDIR)/sg_vpd.Po
+ -rm -f ./$(DEPDIR)/sg_vpd_common.Po
-rm -f ./$(DEPDIR)/sg_vpd_vendor.Po
-rm -f ./$(DEPDIR)/sg_wr_mode.Po
-rm -f ./$(DEPDIR)/sg_write_buffer.Po
diff --git a/src/sg_decode_sense.c b/src/sg_decode_sense.c
index 83f1d1fa..8950cdbd 100644
--- a/src/sg_decode_sense.c
+++ b/src/sg_decode_sense.c
@@ -30,7 +30,7 @@
#include "sg_unaligned.h"
-static const char * version_str = "1.28 20220626";
+static const char * version_str = "1.29 20220711";
#define MY_NAME "sg_decode_sense"
@@ -504,7 +504,7 @@ main(int argc, char *argv[])
printf("%s\n", b);
} else {
if (as_json) {
- sgj_get_sense(jsp, jop, op->sense, op->sense_len);
+ sgj_pr_js_sense(jsp, jop, op->sense, op->sense_len);
if (jsp->pr_out_hr) {
sg_get_sense_str(NULL, op->sense, op->sense_len,
op->verbose, blen, b);
diff --git a/src/sg_inq.c b/src/sg_inq.c
index c9022516..8e5b48d7 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -51,7 +51,11 @@
#include "sg_pt_nvme.h"
#endif
-static const char * version_str = "2.17 20220504"; /* spc6r06 */
+#include "sg_vpd_common.h" /* for shared VPD page processing with sg_vpd */
+
+static const char * version_str = "2.18 20220511"; /* spc6r06 */
+
+#define MY_NAME "sg_inq"
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
@@ -81,36 +85,6 @@ static const char * version_str = "2.17 20220504"; /* spc6r06 */
*/
-/* Following VPD pages are in ascending page number order */
-#define VPD_SUPPORTED_VPDS 0x0
-#define VPD_UNIT_SERIAL_NUM 0x80
-#define VPD_DEVICE_ID 0x83
-#define VPD_SOFTW_INF_ID 0x84
-#define VPD_MAN_NET_ADDR 0x85
-#define VPD_EXT_INQ 0x86 /* Extended Inquiry */
-#define VPD_MODE_PG_POLICY 0x87
-#define VPD_SCSI_PORTS 0x88
-#define VPD_ATA_INFO 0x89
-#define VPD_POWER_CONDITION 0x8a
-#define VPD_DEVICE_CONSTITUENTS 0x8b
-#define VPD_CFA_PROFILE_INFO 0x8c
-#define VPD_POWER_CONSUMPTION 0x8d
-#define VPD_3PARTY_COPY 0x8f
-#define VPD_PROTO_LU 0x90
-#define VPD_PROTO_PORT 0x91
-#define VPD_SCSI_FEATURE_SETS 0x92 /* spc5r11 */
-#define VPD_BLOCK_LIMITS 0xb0
-#define VPD_BLOCK_DEV_CHARS 0xb1
-#define VPD_MAN_ASS_SN 0xb1
-#define VPD_LB_PROVISIONING 0xb2
-#define VPD_REFERRALS 0xb3
-#define VPD_SUP_BLOCK_LENS 0xb4 /* sbc4r01 */
-#define VPD_BLOCK_DEV_C_EXTENS 0xb5 /* sbc4r02 */
-#define VPD_ZBC_DEV_CHARS 0xb6 /* zbc-r01b */
-#define VPD_BLOCK_LIMITS_EXT 0xb7 /* sbc4r08 */
-#define VPD_FORMAT_PRESETS 0xb8 /* sbc4r18 */
-#define VPD_CON_POS_RANGE 0xb9 /* sbc5r01 */
-
#ifndef SG_NVME_VPD_NICR
#define SG_NVME_VPD_NICR 0xde
#endif
@@ -140,7 +114,8 @@ static const char * version_str = "2.17 20220504"; /* spc6r06 */
#define DEF_PT_TIMEOUT 60 /* 60 seconds */
-static uint8_t * rsp_buff;
+uint8_t * rsp_buff;
+
static uint8_t * free_rsp_buff;
static const int rsp_buff_sz = MX_ALLOC_LEN + 1;
@@ -148,8 +123,10 @@ static char xtra_buff[MX_ALLOC_LEN + 1];
static char usn_buff[MX_ALLOC_LEN + 1];
static const char * find_version_descriptor_str(int value);
-static void decode_dev_ids(const char * leadin, uint8_t * buff,
- int len, int do_hex, int verbose);
+static void decode_dev_ids(const char * leadin, uint8_t * buff, int len,
+ struct opts_t * op, sgj_opaque_p jop);
+static int vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
+ int inhex_len);
#if defined(SG_LIB_LINUX) && defined(SG_SCSI_STRINGS) && \
defined(HDIO_GET_IDENTITY)
@@ -159,6 +136,7 @@ struct opts_t;
static void prepare_ata_identify(const struct opts_t * op, int inhex_len);
#endif
+#if 0
struct svpd_values_name_t {
int value;
int subvalue;
@@ -168,59 +146,69 @@ struct svpd_values_name_t {
const char * acron;
const char * name;
};
+#endif
/* Note that this table is sorted by acronym */
-static struct svpd_values_name_t vpd_pg[] = {
- {VPD_ATA_INFO, 0, -1, 0, "ai", "ATA information (SAT)"},
- {VPD_BLOCK_DEV_CHARS, 0, 0, 0, "bdc",
+static struct svpd_values_name_t t10_vpd_pg[] = {
+ {VPD_ATA_INFO, 0, -1, "ai", "ATA information (SAT)"},
+ {VPD_BLOCK_DEV_CHARS, 0, 0, "bdc",
"Block device characteristics (SBC)"},
- {VPD_BLOCK_DEV_C_EXTENS, 0, 0, 0, "bdce", "Block device characteristics "
+ {VPD_BLOCK_DEV_C_EXTENS, 0, 0, "bdce", "Block device characteristics "
"extension (SBC)"},
- {VPD_BLOCK_LIMITS, 0, 0, 0, "bl", "Block limits (SBC)"},
- {VPD_BLOCK_LIMITS_EXT, 0, 0, 0, "ble", "Block limits extension (SBC)"},
- {VPD_CON_POS_RANGE, 0, 0, 0, "cpr", "Concurrent positioning ranges "
+ {VPD_BLOCK_LIMITS, 0, 0, "bl", "Block limits (SBC)"},
+ {VPD_BLOCK_LIMITS_EXT, 0, 0, "ble", "Block limits extension (SBC)"},
+ {VPD_CON_POS_RANGE, 0, 0, "cpr", "Concurrent positioning ranges "
"(SBC)"},
- {VPD_DEVICE_ID, 0, -1, 0, "di", "Device identification"},
+ {VPD_DEVICE_ID, 0, -1, "di", "Device identification"},
#if 0 /* following found in sg_vpd */
- {VPD_DEVICE_ID, VPD_DI_SEL_AS_IS, -1, 0, "di_asis", "Like 'di' "
+ {VPD_DEVICE_ID, VPD_DI_SEL_AS_IS, -1, "di_asis", "Like 'di' "
"but designators ordered as found"},
- {VPD_DEVICE_ID, VPD_DI_SEL_LU, -1, 0, "di_lu", "Device identification, "
+ {VPD_DEVICE_ID, VPD_DI_SEL_LU, -1, "di_lu", "Device identification, "
"lu only"},
- {VPD_DEVICE_ID, VPD_DI_SEL_TPORT, -1, 0, "di_port", "Device "
+ {VPD_DEVICE_ID, VPD_DI_SEL_TPORT, -1, "di_port", "Device "
"identification, target port only"},
- {VPD_DEVICE_ID, VPD_DI_SEL_TARGET, -1, 0, "di_target", "Device "
+ {VPD_DEVICE_ID, VPD_DI_SEL_TARGET, -1, "di_target", "Device "
"identification, target device only"},
#endif
- {VPD_EXT_INQ, 0, -1, 0, "ei", "Extended inquiry data"},
- {VPD_FORMAT_PRESETS, 0, 0, 0, "fp", "Format presets"},
- {VPD_LB_PROVISIONING, 0, 0, 0, "lbpv", "Logical block provisioning "
+ {VPD_EXT_INQ, 0, -1, "ei", "Extended inquiry data"},
+ {VPD_FORMAT_PRESETS, 0, 0, "fp", "Format presets"},
+ {VPD_LB_PROVISIONING, 0, 0, "lbpv", "Logical block provisioning "
"(SBC)"},
- {VPD_MAN_NET_ADDR, 0, -1, 0, "mna", "Management network addresses"},
- {VPD_MODE_PG_POLICY, 0, -1, 0, "mpp", "Mode page policy"},
- {VPD_POWER_CONDITION, 0, -1, 0, "po", "Power condition"},
- {VPD_POWER_CONSUMPTION, 0, -1, 0, "psm", "Power consumption"},
- {VPD_PROTO_LU, 0, 0x0, 0, "pslu", "Protocol-specific logical unit "
+ {VPD_MAN_NET_ADDR, 0, -1, "mna", "Management network addresses"},
+ {VPD_MODE_PG_POLICY, 0, -1, "mpp", "Mode page policy"},
+ {VPD_POWER_CONDITION, 0, -1, "po", "Power condition"},
+ {VPD_POWER_CONSUMPTION, 0, -1, "psm", "Power consumption"},
+ {VPD_PROTO_LU, 0, 0x0, "pslu", "Protocol-specific logical unit "
"information"},
- {VPD_PROTO_PORT, 0, 0x0, 0, "pspo", "Protocol-specific port information"},
- {VPD_REFERRALS, 0, 0, 0, "ref", "Referrals (SBC)"},
- {VPD_SUP_BLOCK_LENS, 0, 0, 0, "sbl", "Supported block lengths and "
+ {VPD_PROTO_PORT, 0, 0x0, "pspo", "Protocol-specific port information"},
+ {VPD_REFERRALS, 0, 0, "ref", "Referrals (SBC)"},
+ {VPD_SUP_BLOCK_LENS, 0, 0, "sbl", "Supported block lengths and "
"protection types (SBC)"},
- {VPD_SCSI_FEATURE_SETS, 0, -1, 0, "sfs", "SCSI Feature sets"},
- {VPD_SOFTW_INF_ID, 0, -1, 0, "sii", "Software interface identification"},
- {VPD_NOPE_WANT_STD_INQ, 0, -1, 0, "sinq", "Standard inquiry response"},
- {VPD_UNIT_SERIAL_NUM, 0, -1, 0, "sn", "Unit serial number"},
- {VPD_SCSI_PORTS, 0, -1, 0, "sp", "SCSI ports"},
- {VPD_SUPPORTED_VPDS, 0, -1, 0, "sv", "Supported VPD pages"},
- {VPD_3PARTY_COPY, 0, -1, 0, "tpc", "Third party copy"},
- {VPD_ZBC_DEV_CHARS, 0, -1, 0, "zbdch", "Zoned block device "
+ {VPD_SCSI_FEATURE_SETS, 0, -1, "sfs", "SCSI Feature sets"},
+ {VPD_SOFTW_INF_ID, 0, -1, "sii", "Software interface identification"},
+ {VPD_NOPE_WANT_STD_INQ, 0, -1, "sinq", "Standard inquiry response"},
+ {VPD_UNIT_SERIAL_NUM, 0, -1, "sn", "Unit serial number"},
+ {VPD_SCSI_PORTS, 0, -1, "sp", "SCSI ports"},
+ {VPD_SUPPORTED_VPDS, 0, -1, "sv", "Supported VPD pages"},
+ {VPD_3PARTY_COPY, 0, -1, "tpc", "Third party copy"},
+ {VPD_ZBC_DEV_CHARS, 0, -1, "zbdch", "Zoned block device "
"characteristics"},
+ {0, 0, 0, NULL, NULL},
+};
+
+static struct svpd_values_name_t alt_t10_vpd_pg[] = {
+ {VPD_POWER_CONDITION, 0, -1, "pc", "Power condition"},
+ {0, 0, 0, NULL, NULL},
+};
+
+static struct svpd_values_name_t vs_vpd_pg[] = {
/* Following are vendor specific */
- {SG_NVME_VPD_NICR, 0, -1, 1, "nicr",
+ {SG_NVME_VPD_NICR, 0, -1, "nicr",
"NVMe Identify Controller Response (sg3_utils)"},
- {VPD_RDAC_VAC, 0, -1, 1, "rdac_vac", "RDAC volume access control (RDAC)"},
- {VPD_RDAC_VERS, 0, -1, 1, "rdac_vers", "RDAC software version (RDAC)"},
- {VPD_UPR_EMC, 0, -1, 1, "upr", "Unit path report (EMC)"},
- {0, 0, 0, 0, NULL, NULL},
+ {VPD_RDAC_VAC, 0, -1, "rdac_vac", "RDAC volume access control (RDAC)"},
+ {VPD_RDAC_VERS, 0, -1, "rdac_vers", "RDAC software version (RDAC)"},
+ {VPD_UPR_EMC, 0, -1, "upr", "Unit path report (EMC)"},
+ {0, 0, 0, NULL, NULL},
};
static struct option long_options[] = {
@@ -255,38 +243,6 @@ static struct option long_options[] = {
{0, 0, 0, 0},
};
-struct opts_t {
- bool do_ata;
- bool do_decode;
- bool do_descriptors;
- bool do_export;
- bool do_force;
- bool do_only; /* --only after standard inq don't fetch VPD page 0x80 */
- bool verbose_given;
- bool version_given;
- bool do_vpd;
- bool page_given;
- bool possible_nvme;
- int do_block;
- int do_cmddt;
- int do_help;
- int do_hex;
- int do_long;
- int do_raw;
- int do_vendor;
- int verbose;
- int resp_len;
- int page_num;
- int page_pdt;
- int num_pages;
- const char * page_arg;
- const char * device_name;
- const char * inhex_fn;
-#ifdef SG_SCSI_STRINGS
- bool opt_new;
-#endif
-};
-
static void
usage()
@@ -296,23 +252,26 @@ usage()
pr2serr("Usage: sg_inq [--ata] [--block=0|1] [--cmddt] [--descriptors] "
"[--export]\n"
- " [--extended] [--help] [--hex] [--id] [--inhex=FN] "
- "[--len=LEN]\n"
- " [--long] [--maxlen=LEN] [--only] [--page=PG] "
- "[--raw]\n"
- " [--vendor] [--verbose] [--version] [--vpd] "
- "DEVICE\n"
+ " [--extended] [--help] [--hex] [--id] "
+ "[--inhex=FN]\n"
+ " [--json[=JO]] [--len=LEN] [--long] "
+ "[--maxlen=LEN]\n"
+ " [--only] [--page=PG] [--raw] [--vendor] "
+ "[--verbose]\n"
+ " [--version] [--vpd] DEVICE\n"
" where:\n"
" --ata|-a treat DEVICE as (directly attached) ATA "
"device\n");
#else
pr2serr("Usage: sg_inq [--block=0|1] [--cmddt] [--descriptors] "
"[--export]\n"
- " [--extended] [--help] [--hex] [--id] [--inhex=FN] "
- "[--len=LEN]\n"
- " [--long] [--maxlen=LEN] [--only] [--page=PG] "
- "[--raw]\n"
- " [--verbose] [--version] [--vpd] DEVICE\n"
+ " [--extended] [--help] [--hex] [--id] "
+ "[--inhex=FN]\n"
+ " [--json[=JO]] [--len=LEN] [--long] "
+ "[--maxlen=LEN]\n"
+ " [--only] [--page=PG] [--raw] [--verbose] "
+ "[--version]\n"
+ " [--vpd] DEVICE\n"
" where:\n");
#endif
pr2serr(" --block=0|1 0-> open(non-blocking); 1-> "
@@ -340,6 +299,9 @@ usage()
"DEVICE;\n"
" if used with --raw then read binary "
"from FN\n"
+ " --json[=JO]|-j[JO] output in JSON instead of human "
+ "readable text.\n"
+ " Use --json=? for JSON help\n"
" --len=LEN|-l LEN requested response length (def: 0 "
"-> fetch 36\n"
" bytes first, then fetch again as "
@@ -462,18 +424,18 @@ new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
#ifdef SG_LIB_LINUX
#ifdef SG_SCSI_STRINGS
- c = getopt_long(argc, argv, "aB:cdeEfhHiI:l:Lm:NoOp:rsuvVx",
+ c = getopt_long(argc, argv, "aB:cdeEfhHiI:j::l:Lm:NoOp:rsuvVx",
long_options, &option_index);
#else
- c = getopt_long(argc, argv, "B:cdeEfhHiI:l:Lm:op:rsuvVx",
+ c = getopt_long(argc, argv, "B:cdeEfhHiI:j::l:Lm:op:rsuvVx",
long_options, &option_index);
#endif /* SG_SCSI_STRINGS */
#else /* SG_LIB_LINUX */
#ifdef SG_SCSI_STRINGS
- c = getopt_long(argc, argv, "B:cdeEfhHiI:l:Lm:NoOp:rsuvVx",
+ c = getopt_long(argc, argv, "B:cdeEfhHiI:j::l:Lm:NoOp:rsuvVx",
long_options, &option_index);
#else
- c = getopt_long(argc, argv, "B:cdeEfhHiI:l:Lm:op:rsuvVx",
+ c = getopt_long(argc, argv, "B:cdeEfhHiI:j::l:Lm:op:rsuvVx",
long_options, &option_index);
#endif /* SG_SCSI_STRINGS */
#endif /* SG_LIB_LINUX */
@@ -513,7 +475,7 @@ new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
case 'x':
op->do_decode = true;
op->do_vpd = true;
- op->page_num = VPD_EXT_INQ;
+ op->vpd_pn = VPD_EXT_INQ;
op->page_given = true;
break;
case 'f':
@@ -522,6 +484,20 @@ new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
case 'h':
++op->do_help;
break;
+ case 'j':
+ if (! sgj_init_state(&op->json_st, optarg)) {
+ int bad_char = op->json_st.first_bad_char;
+ char e[1500];
+
+ if (bad_char) {
+ pr2serr("bad argument to --json= option, unrecognized "
+ "character '%c'\n\n", bad_char);
+ }
+ sg_json_usage(0, e, sizeof(e));
+ pr2serr("%s", e);
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ break;
case 'o':
op->do_only = true;
break;
@@ -535,7 +511,7 @@ new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
case 'i':
op->do_decode = true;
op->do_vpd = true;
- op->page_num = VPD_DEVICE_ID;
+ op->vpd_pn = VPD_DEVICE_ID;
op->page_given = true;
break;
case 'I':
@@ -553,7 +529,7 @@ new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
pr2serr("Changing that '--maxlen=' value to 4\n");
n = 4;
}
- op->resp_len = n;
+ op->maxlen = n;
break;
case 'L':
++op->do_long;
@@ -566,7 +542,7 @@ new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
return 0;
#endif
case 'p':
- op->page_arg = optarg;
+ op->page_str = optarg;
op->page_given = true;
break;
case 'r':
@@ -628,14 +604,14 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
switch (*cp) {
case '3':
if ('6' == *(cp + 1)) {
- op->resp_len = 36;
+ op->maxlen = 36;
--plen;
++cp;
} else
jmp_out = true;
break;
case 'a':
- op->page_num = VPD_ATA_INFO;
+ op->vpd_pn = VPD_ATA_INFO;
op->do_vpd = true;
op->page_given = true;
++op->num_pages;
@@ -646,7 +622,7 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
break;
#endif
case 'b':
- op->page_num = VPD_BLOCK_LIMITS;
+ op->vpd_pn = VPD_BLOCK_LIMITS;
op->do_vpd = true;
op->page_given = true;
++op->num_pages;
@@ -674,7 +650,7 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
++op->do_hex;
break;
case 'i':
- op->page_num = VPD_DEVICE_ID;
+ op->vpd_pn = VPD_DEVICE_ID;
op->do_vpd = true;
op->page_given = true;
++op->num_pages;
@@ -683,13 +659,13 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
++op->do_long;
break;
case 'm':
- op->page_num = VPD_MAN_NET_ADDR;
+ op->vpd_pn = VPD_MAN_NET_ADDR;
op->do_vpd = true;
++op->num_pages;
op->page_given = true;
break;
case 'M':
- op->page_num = VPD_MODE_PG_POLICY;
+ op->vpd_pn = VPD_MODE_PG_POLICY;
op->do_vpd = true;
op->page_given = true;
++op->num_pages;
@@ -703,7 +679,7 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
case 'O':
break;
case 'P':
- op->page_num = VPD_UPR_EMC;
+ op->vpd_pn = VPD_UPR_EMC;
op->do_vpd = true;
op->page_given = true;
++op->num_pages;
@@ -712,7 +688,7 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
++op->do_raw;
break;
case 's':
- op->page_num = VPD_SCSI_PORTS;
+ op->vpd_pn = VPD_SCSI_PORTS;
op->do_vpd = true;
op->page_given = true;
++op->num_pages;
@@ -728,7 +704,7 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
op->version_given = true;
break;
case 'x':
- op->page_num = VPD_EXT_INQ;
+ op->vpd_pn = VPD_EXT_INQ;
op->do_vpd = true;
op->page_given = true;
++op->num_pages;
@@ -770,9 +746,9 @@ old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
pr2serr("Changing that '-l=' value to 4\n");
n = 4;
}
- op->resp_len = n;
+ op->maxlen = n;
} else if (0 == strncmp("p=", cp, 2)) {
- op->page_arg = cp + 2;
+ op->page_str = cp + 2;
op->page_given = true;
} else if (0 == strncmp("-old", cp, 4))
;
@@ -836,7 +812,15 @@ sdp_find_vpd_by_acron(const char * ap)
{
const struct svpd_values_name_t * vnp;
- for (vnp = vpd_pg; vnp->acron; ++vnp) {
+ for (vnp = t10_vpd_pg; vnp->acron; ++vnp) {
+ if (0 == strcmp(vnp->acron, ap))
+ return vnp;
+ }
+ for (vnp = alt_t10_vpd_pg; vnp->acron; ++vnp) {
+ if (0 == strcmp(vnp->acron, ap))
+ return vnp;
+ }
+ for (vnp = vs_vpd_pg; vnp->acron; ++vnp) {
if (0 == strcmp(vnp->acron, ap))
return vnp;
}
@@ -848,7 +832,16 @@ enumerate_vpds()
{
const struct svpd_values_name_t * vnp;
- for (vnp = vpd_pg; vnp->acron; ++vnp) {
+ for (vnp = t10_vpd_pg; vnp->acron; ++vnp) {
+ if (vnp->name) {
+ if (vnp->value < 0)
+ printf(" %-10s -1 %s\n", vnp->acron, vnp->name);
+ else
+ printf(" %-10s 0x%02x %s\n", vnp->acron, vnp->value,
+ vnp->name);
+ }
+ }
+ for (vnp = vs_vpd_pg; vnp->acron; ++vnp) {
if (vnp->name) {
if (vnp->value < 0)
printf(" %-10s -1 %s\n", vnp->acron, vnp->name);
@@ -1053,6 +1046,61 @@ get_vpd_page_str(int vpd_page_num, int scsi_ptype)
}
}
+static int
+svpd_inhex_decode_all(struct opts_t * op, sgj_opaque_p jop)
+{
+ int k, res, pn;
+ int max_pn = 255;
+ int bump, off;
+ int in_len = op->maxlen;
+ int prev_pn = -1;
+ uint8_t vpd0_buff[512];
+ uint8_t * rp = vpd0_buff;
+
+ if (op->vpd_pn > 0)
+ max_pn = op->vpd_pn;
+
+ res = 0;
+ if (op->page_given && (VPD_NOPE_WANT_STD_INQ == op->vpd_pn))
+ return vpd_decode(-1, op, jop, in_len);
+
+ for (k = 0, off = 0; off < in_len; ++k, off += bump) {
+ rp = rsp_buff + off;
+ pn = rp[1];
+ bump = sg_get_unaligned_be16(rp + 2) + 4;
+ if ((off + bump) > in_len) {
+ pr2serr("%s: page 0x%x size (%d) exceeds buffer\n", __func__,
+ pn, bump);
+ bump = in_len - off;
+ }
+ if (op->page_given && (pn != op->vpd_pn))
+ continue;
+ if (pn <= prev_pn) {
+ pr2serr("%s: prev_pn=0x%x, this pn=0x%x, not ascending so "
+ "exit\n", __func__, prev_pn, pn);
+ break;
+ }
+ prev_pn = pn;
+ op->vpd_pn = pn;
+ if (pn > max_pn) {
+ if (op->verbose > 2)
+ pr2serr("%s: skipping as this pn=0x%x exceeds "
+ "max_pn=0x%x\n", __func__, pn, max_pn);
+ continue;
+ }
+ if (op->do_long)
+ printf("[0x%x] ", pn);
+
+ op->inhex_off = off;
+ res = vpd_decode(-1, op, jop, in_len);
+ if (SG_LIB_CAT_OTHER == res) {
+ ; // xxxxx
+ }
+ }
+ return res;
+}
+
+
static void
decode_supported_vpd(uint8_t * buff, int len, int do_hex)
{
@@ -1154,196 +1202,115 @@ decode_ascii_inf(uint8_t * buff, int len, int do_hex)
}
static void
-decode_id_vpd(uint8_t * buff, int len, int do_hex, int verbose)
+decode_id_vpd(uint8_t * buff, int len, struct opts_t * op, sgj_opaque_p jap)
{
if (len < 4) {
pr2serr("Device identification VPD page length too "
"short=%d\n", len);
return;
}
- decode_dev_ids("Device identification", buff + 4, len - 4, do_hex,
- verbose);
-}
-
-static const char * assoc_arr[] =
-{
- "addressed logical unit",
- "target port", /* that received request; unless SCSI ports VPD */
- "target device that contains addressed lu",
- "reserved [0x3]",
-};
-
-static const char * network_service_type_arr[] =
-{
- "unspecified",
- "storage configuration service",
- "diagnostics",
- "status",
- "logging",
- "code download",
- "copy service",
- "administrative configuration service",
- "[0x8]", "[0x9]", "[0xa]", "[0xb]", "[0xc]", "[0xd]",
- "[0xe]", "[0xf]", "[0x10]", "[0x11]", "[0x12]", "[0x13]", "[0x14]",
- "[0x15]", "[0x16]", "[0x17]", "[0x18]", "[0x19]", "[0x1a]",
- "[0x1b]", "[0x1c]", "[0x1d]", "[0x1e]", "[0x1f]",
-};
-
-/* VPD_MAN_NET_ADDR */
-static void
-decode_net_man_vpd(uint8_t * buff, int len, int do_hex)
-{
- int k, bump, na_len;
- uint8_t * bp;
-
- if (len < 4) {
- pr2serr("Management network addresses VPD page length too short=%d\n",
- len);
- return;
- }
- if (do_hex > 2) {
- hex2stdout(buff, len, -1);
- return;
- }
- len -= 4;
- bp = buff + 4;
- for (k = 0; k < len; k += bump, bp += bump) {
- printf(" %s, Service type: %s\n",
- assoc_arr[(bp[0] >> 5) & 0x3],
- network_service_type_arr[bp[0] & 0x1f]);
- na_len = sg_get_unaligned_be16(bp + 2);
- bump = 4 + na_len;
- if ((k + bump) > len) {
- pr2serr("Management network addresses VPD page, short "
- "descriptor length=%d, left=%d\n", bump, (len - k));
- return;
- }
- if (na_len > 0) {
- if (do_hex) {
- printf(" Network address:\n");
- hex2stdout(bp + 4, na_len, 0);
- } else
- printf(" %s\n", bp + 4);
- }
- }
-}
-
-static const char * mode_page_policy_arr[] =
-{
- "shared",
- "per target port",
- "per initiator port",
- "per I_T nexus",
-};
-
-/* VPD_MODE_PG_POLICY */
-static void
-decode_mode_policy_vpd(uint8_t * buff, int len, int do_hex)
-{
- int k, bump;
- uint8_t * bp;
-
- if (len < 4) {
- pr2serr("Mode page policy VPD page length too short=%d\n", len);
- return;
- }
- if (do_hex > 2) {
- hex2stdout(buff, len, -1);
- return;
- }
- len -= 4;
- bp = buff + 4;
- for (k = 0; k < len; k += bump, bp += bump) {
- bump = 4;
- if ((k + bump) > len) {
- pr2serr("Mode page policy VPD page, short "
- "descriptor length=%d, left=%d\n", bump, (len - k));
- return;
- }
- if (do_hex)
- hex2stdout(bp, 4, (1 == do_hex) ? 1 : -1);
- else {
- printf(" Policy page code: 0x%x", (bp[0] & 0x3f));
- if (bp[1])
- printf(", subpage code: 0x%x\n", bp[1]);
- else
- printf("\n");
- printf(" MLUS=%d, Policy: %s\n", !!(bp[2] & 0x80),
- mode_page_policy_arr[bp[2] & 0x3]);
- }
- }
+ decode_dev_ids("Device identification", buff + 4, len - 4, op, jap);
}
/* VPD_SCSI_PORTS */
static void
-decode_scsi_ports_vpd(uint8_t * buff, int len, int do_hex, int verbose)
+decode_scsi_ports_vpd(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap)
{
int k, bump, rel_port, ip_tid_len, tpd_len;
uint8_t * bp;
+ sgj_state * jsp = &op->json_st;
+ sgj_opaque_p jo2p;
if (len < 4) {
pr2serr("SCSI Ports VPD page length too short=%d\n", len);
return;
}
- if (do_hex > 2) {
+ if (op->do_hex > 2) {
hex2stdout(buff, len, -1);
return;
}
len -= 4;
bp = buff + 4;
for (k = 0; k < len; k += bump, bp += bump) {
+ jo2p = sgj_new_unattached_object(jsp);
rel_port = sg_get_unaligned_be16(bp + 2);
- printf("Relative port=%d\n", rel_port);
+ sgj_pr_hr(jsp, "Relative port=%d\n", rel_port);
+ sgj_add_nv_i(jsp, jo2p, "relative_port", rel_port);
ip_tid_len = sg_get_unaligned_be16(bp + 6);
bump = 8 + ip_tid_len;
if ((k + bump) > len) {
pr2serr("SCSI Ports VPD page, short descriptor "
"length=%d, left=%d\n", bump, (len - k));
+ sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p);
return;
}
if (ip_tid_len > 0) {
- if (do_hex) {
+ if (op->do_hex) {
printf(" Initiator port transport id:\n");
- hex2stdout((bp + 8), ip_tid_len, (1 == do_hex) ? 1 : -1);
+ hex2stdout((bp + 8), ip_tid_len,
+ (1 == op->do_hex) ? 1 : -1);
} else {
char b[1024];
- printf("%s", sg_decode_transportid_str(" ", bp + 8,
- ip_tid_len, true, sizeof(b), b));
+ sg_decode_transportid_str(" ", bp + 8, ip_tid_len,
+ true, sizeof(b), b);
+ if (jsp->pr_as_json)
+ sgj_add_nv_s(jsp, jo2p, "initiator_port_transport_id", b);
+ sgj_pr_hr(jsp, "%s",
+ sg_decode_transportid_str(" ", bp + 8,
+ ip_tid_len, true, sizeof(b), b));
}
}
tpd_len = sg_get_unaligned_be16(bp + bump + 2);
if ((k + bump + tpd_len + 4) > len) {
pr2serr("SCSI Ports VPD page, short descriptor(tgt) "
"length=%d, left=%d\n", bump, (len - k));
+ sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p);
return;
}
if (tpd_len > 0) {
- printf(" Target port descriptor(s):\n");
- if (do_hex)
- hex2stdout(bp + bump + 4, tpd_len, (1 == do_hex) ? 1 : -1);
- else
+ sgj_pr_hr(jsp, " Target port descriptor(s):\n");
+ if (op->do_hex)
+ hex2stdout(bp + bump + 4, tpd_len,
+ (1 == op->do_hex) ? 1 : -1);
+ else {
+ sgj_opaque_p ja2p = sgj_new_named_array(jsp, jo2p,
+ "target_port_descriptor_list");
+
decode_dev_ids("SCSI Ports", bp + bump + 4, tpd_len,
- do_hex, verbose);
+ op, ja2p);
+ }
}
bump += tpd_len + 4;
+ sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p);
}
}
/* These are target port, device server (i.e. target) and LU identifiers */
static void
-decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
- int verbose)
+decode_dev_ids(const char * leadin, uint8_t * buff, int len,
+ struct opts_t * op, sgj_opaque_p jap)
{
int u, j, m, id_len, p_id, c_set, piv, assoc, desig_type, i_len;
- int off, ci_off, c_id, d_id, naa, vsi, k;
+ int off, ci_off, c_id, d_id, naa, vsi, k, n;
uint64_t vsei, id_ext, ccc_id;
const uint8_t * bp;
const uint8_t * ip;
const char * cp;
- char b[64];
+ sgj_state * jsp = &op->json_st;
+ char b[256];
+ char d[64];
+ static const int blen = sizeof(b);
+ static const int dlen = sizeof(d);
- if (buff[2] != 0) {
+ if (jsp->pr_as_json) {
+ int ret = filter_json_dev_ids(buff, len, -1, op, jap);
+
+ if (ret || (! jsp->pr_out_hr))
+ return;
+ }
+ if (buff[2] > 2) { /* SPC-3,4,5 buff[2] is upper byte of length */
/*
* Reference the 3rd byte of the first Identification descriptor
* of a page 83 reply to determine whether the reply is compliant
@@ -1363,7 +1330,8 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
desig_type = 3;
j = 1;
off = 16;
- printf(" Pre-SPC descriptor, descriptor length: %d\n", i_len);
+ sgj_pr_hr(jsp, " Pre-SPC descriptor, descriptor length: %d\n",
+ i_len);
goto decode;
}
@@ -1373,8 +1341,8 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
bp = buff + off;
i_len = bp[3];
id_len = i_len + 4;
- printf(" Designation descriptor number %d, "
- "descriptor length: %d\n", j, id_len);
+ sgj_pr_hr(jsp, " Designation descriptor number %d, "
+ "descriptor length: %d\n", j, id_len);
if ((off + id_len) > len) {
pr2serr("%s VPD page error: designator length longer "
"than\n remaining response length=%d\n", leadin,
@@ -1389,18 +1357,20 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
desig_type = (bp[1] & 0xf);
decode:
if (piv && ((1 == assoc) || (2 == assoc)))
- printf(" transport: %s\n",
- sg_get_trans_proto_str(p_id, sizeof(b), b));
+ sgj_pr_hr(jsp, " transport: %s\n",
+ sg_get_trans_proto_str(p_id, dlen, d));
+ n = 0;
cp = sg_get_desig_type_str(desig_type);
- printf(" designator_type: %s, ", cp ? cp : "-");
+ n += sg_scnpr(b + n, blen - n, " designator_type: %s, ",
+ cp ? cp : "-");
cp = sg_get_desig_code_set_str(c_set);
- printf("code_set: %s\n", cp ? cp : "-");
+ sgj_pr_hr(jsp, "%scode_set: %s\n", b, cp ? cp : "-");
cp = sg_get_desig_assoc_str(assoc);
- printf(" associated with the %s\n", cp ? cp : "-");
- if (do_hex) {
- printf(" designator header(hex): %.2x %.2x %.2x %.2x\n",
+ sgj_pr_hr(jsp, " associated with the %s\n", cp ? cp : "-");
+ if (op->do_hex) {
+ sgj_pr_hr(jsp, " designator header(hex): %.2x %.2x %.2x %.2x\n",
bp[0], bp[1], bp[2], bp[3]);
- printf(" designator:\n");
+ sgj_pr_hr(jsp, " designator:\n");
hex2stdout(ip, i_len, 0);
continue;
}
@@ -1414,37 +1384,44 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
k = 1;
}
if (k)
- printf(" vendor specific: %.*s\n", i_len, ip);
+ sgj_pr_hr(jsp, " vendor specific: %.*s\n", i_len, ip);
else {
- printf(" vendor specific:\n");
+ sgj_pr_hr(jsp, " vendor specific:\n");
hex2stdout(ip, i_len, -1);
}
break;
case 1: /* T10 vendor identification */
- printf(" vendor id: %.8s\n", ip);
+ sgj_pr_hr(jsp, " vendor id: %.8s\n", ip);
if (i_len > 8) {
if ((2 == c_set) || (3 == c_set)) { /* ASCII or UTF-8 */
- printf(" vendor specific: %.*s\n", i_len - 8, ip + 8);
+ sgj_pr_hr(jsp, " vendor specific: %.*s\n", i_len - 8,
+ ip + 8);
} else {
- printf(" vendor specific: 0x");
+ n = 0;
+ n += sg_scnpr(b + n, blen - n,
+ " vendor specific: 0x");
for (m = 8; m < i_len; ++m)
- printf("%02x", (unsigned int)ip[m]);
- printf("\n");
+ n += sg_scnpr(b + n, blen - n, "%02x", ip[m]);
+ sgj_pr_hr(jsp, "%s\n", b);
}
}
break;
case 2: /* EUI-64 based */
- printf(" EUI-64 based %d byte identifier\n", i_len);
+ sgj_pr_hr(jsp, " EUI-64 based %d byte identifier\n", i_len);
if (1 != c_set) {
pr2serr(" << expected binary code_set (1)>>\n");
hex2stderr(ip, i_len, -1);
break;
}
ci_off = 0;
+ n = 0;
+ b[0] = '\0';
if (16 == i_len) {
ci_off = 8;
id_ext = sg_get_unaligned_be64(ip);
- printf(" Identifier extension: 0x%" PRIx64 "\n", id_ext);
+ n += sg_scnpr(b + n, blen - n,
+ " Identifier extension: 0x%" PRIx64 "\n",
+ id_ext);
} else if ((8 != i_len) && (12 != i_len)) {
pr2serr(" << can only decode 8, 12 and 16 "
"byte ids>>\n");
@@ -1452,15 +1429,17 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
break;
}
ccc_id = sg_get_unaligned_be64(ip + ci_off);
- printf(" IEEE identifier: 0x%" PRIx64 "\n", ccc_id);
+ sgj_pr_hr(jsp, "%s IEEE identifier: 0x%" PRIx64 "\n", b,
+ ccc_id);
if (12 == i_len) {
d_id = sg_get_unaligned_be32(ip + 8);
- printf(" Directory ID: 0x%x\n", d_id);
+ sgj_pr_hr(jsp, " Directory ID: 0x%x\n", d_id);
}
- printf(" [0x");
+ n = 0;
+ n += sg_scnpr(b + n, blen - n, " [0x");
for (m = 0; m < i_len; ++m)
- printf("%02x", (unsigned int)ip[m]);
- printf("]\n");
+ n += sg_scnpr(b + n, blen - n, "%02x", ip[m]);
+ sgj_pr_hr(jsp, "%s]\n", b);
break;
case 3: /* NAA <n> */
naa = (ip[0] >> 4) & 0xff;
@@ -1481,14 +1460,16 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
d_id = (((ip[0] & 0xf) << 8) | ip[1]);
c_id = sg_get_unaligned_be24(ip + 2);
vsi = sg_get_unaligned_be24(ip + 5);
- printf(" NAA 2, vendor specific identifier A: 0x%x\n",
- d_id);
- printf(" AOI: 0x%x\n", c_id);
- printf(" vendor specific identifier B: 0x%x\n", vsi);
- printf(" [0x");
+ sgj_pr_hr(jsp, " NAA 2, vendor specific identifier A: "
+ "0x%x\n", d_id);
+ sgj_pr_hr(jsp, " AOI: 0x%x\n", c_id);
+ sgj_pr_hr(jsp, " vendor specific identifier B: 0x%x\n",
+ vsi);
+ n = 0;
+ n += sg_scnpr(b + n, blen - n, " [0x");
for (m = 0; m < 8; ++m)
- printf("%02x", (unsigned int)ip[m]);
- printf("]\n");
+ n += sg_scnpr(b + n, blen - n, "%02x", ip[m]);
+ sgj_pr_hr(jsp, "%s]\n", b);
break;
case 3: /* NAA 3: Locally assigned */
if (8 != i_len) {
@@ -1497,11 +1478,12 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
hex2stderr(ip, i_len, -1);
break;
}
- printf(" NAA 3, Locally assigned:\n");
- printf(" [0x");
+ sgj_pr_hr(jsp, " NAA 3, Locally assigned:\n");
+ n = 0;
+ n += sg_scnpr(b + n, blen - n, " [0x");
for (m = 0; m < 8; ++m)
- printf("%02x", (unsigned int)ip[m]);
- printf("]\n");
+ n += sg_scnpr(b + n, blen - n, "%02x", ip[m]);
+ sgj_pr_hr(jsp, "%s]\n", b);
break;
case 5: /* NAA 5: IEEE Registered */
if (8 != i_len) {
@@ -1517,13 +1499,14 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
vsei <<= 8;
vsei |= ip[3 + m];
}
- printf(" NAA 5, AOI: 0x%x\n", c_id);
- printf(" Vendor Specific Identifier: 0x%" PRIx64
- "\n", vsei);
- printf(" [0x");
+ sgj_pr_hr(jsp, " NAA 5, AOI: 0x%x\n", c_id);
+ n = 0;
+ n += sg_scnpr(b + n, blen - n, " Vendor Specific "
+ "Identifier: 0x%" PRIx64 "\n", vsei);
+ n += sg_scnpr(b + n, blen - n, " [0x");
for (m = 0; m < 8; ++m)
- printf("%02x", (unsigned int)ip[m]);
- printf("]\n");
+ n += sg_scnpr(b + n, blen - n, "%02x", ip[m]);
+ sgj_pr_hr(jsp, "%s]\n", b);
break;
case 6: /* NAA 6: IEEE Registered extended */
if (16 != i_len) {
@@ -1539,16 +1522,17 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
vsei <<= 8;
vsei |= ip[3 + m];
}
- printf(" NAA 6, AOI: 0x%x\n", c_id);
- printf(" Vendor Specific Identifier: 0x%" PRIx64 "\n",
- vsei);
+ sgj_pr_hr(jsp, " NAA 6, AOI: 0x%x\n", c_id);
+ sgj_pr_hr(jsp, " Vendor Specific Identifier: 0x%"
+ PRIx64 "\n", vsei);
vsei = sg_get_unaligned_be64(ip + 8);
- printf(" Vendor Specific Identifier Extension: "
- "0x%" PRIx64 "\n", vsei);
- printf(" [0x");
+ sgj_pr_hr(jsp, " Vendor Specific Identifier Extension: "
+ "0x%" PRIx64 "\n", vsei);
+ n = 0;
+ n += sg_scnpr(b + n, blen - n, " [0x");
for (m = 0; m < 16; ++m)
- printf("%02x", (unsigned int)ip[m]);
- printf("]\n");
+ n += sg_scnpr(b + n, blen - n, "%02x", ip[m]);
+ sgj_pr_hr(jsp, "%s]\n", b);
break;
default:
pr2serr(" << bad NAA nibble , expect 2, 3, 5 or 6, "
@@ -1565,7 +1549,7 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
break;
}
d_id = sg_get_unaligned_be16(ip + 2);
- printf(" Relative target port: 0x%x\n", d_id);
+ sgj_pr_hr(jsp, " Relative target port: 0x%x\n", d_id);
break;
case 5: /* (primary) Target port group */
if ((1 != c_set) || (1 != assoc) || (4 != i_len)) {
@@ -1575,7 +1559,7 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
break;
}
d_id = sg_get_unaligned_be16(ip + 2);
- printf(" Target port group: 0x%x\n", d_id);
+ sgj_pr_hr(jsp, " Target port group: 0x%x\n", d_id);
break;
case 6: /* Logical unit group */
if ((1 != c_set) || (0 != assoc) || (4 != i_len)) {
@@ -1585,7 +1569,7 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
break;
}
d_id = sg_get_unaligned_be16(ip + 2);
- printf(" Logical unit group: 0x%x\n", d_id);
+ sgj_pr_hr(jsp, " Logical unit group: 0x%x\n", d_id);
break;
case 7: /* MD5 logical unit identifier */
if ((1 != c_set) || (0 != assoc)) {
@@ -1594,13 +1578,16 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
hex2stderr(ip, i_len, -1);
break;
}
- printf(" MD5 logical unit identifier:\n");
- hex2stdout(ip, i_len, -1);
+ sgj_pr_hr(jsp, " MD5 logical unit identifier:\n");
+ if (jsp->pr_out_hr)
+ sgj_pr_str_out_hr(jsp, (const char *)ip, i_len);
+ else
+ hex2stdout(ip, i_len, -1);
break;
case 8: /* SCSI name string */
if (3 != c_set) {
if (2 == c_set) {
- if (verbose)
+ if (op->verbose)
pr2serr(" << expected UTF-8, use ASCII>>\n");
} else {
pr2serr(" << expected UTF-8 code_set>>\n");
@@ -1608,33 +1595,36 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
break;
}
}
- printf(" SCSI name string:\n");
+ sgj_pr_hr(jsp, " SCSI name string:\n");
/* does %s print out UTF-8 ok??
* Seems to depend on the locale. Looks ok here with my
* locale setting: en_AU.UTF-8
*/
- printf(" %.*s\n", i_len, (const char *)ip);
+ sgj_pr_hr(jsp, " %.*s\n", i_len, (const char *)ip);
break;
case 9: /* Protocol specific port identifier */
/* added in spc4r36, PIV must be set, proto_id indicates */
/* whether UAS (USB) or SOP (PCIe) or ... */
if (! piv)
- printf(" >>>> Protocol specific port identifier "
- "expects protocol\n"
- " identifier to be valid and it is not\n");
+ pr2serr(" >>>> Protocol specific port identifier "
+ "expects protocol\n"
+ " identifier to be valid and it is not\n");
if (TPROTO_UAS == p_id) {
- printf(" USB device address: 0x%x\n", 0x7f & ip[0]);
- printf(" USB interface number: 0x%x\n", ip[2]);
+ sgj_pr_hr(jsp, " USB device address: 0x%x\n",
+ 0x7f & ip[0]);
+ sgj_pr_hr(jsp, " USB interface number: 0x%x\n", ip[2]);
} else if (TPROTO_SOP == p_id) {
- printf(" PCIe routing ID, bus number: 0x%x\n", ip[0]);
- printf(" function number: 0x%x\n", ip[1]);
- printf(" [or device number: 0x%x, function number: "
- "0x%x]\n", (0x1f & (ip[1] >> 3)), 0x7 & ip[1]);
+ sgj_pr_hr(jsp, " PCIe routing ID, bus number: 0x%x\n",
+ ip[0]);
+ sgj_pr_hr(jsp, " function number: 0x%x\n", ip[1]);
+ sgj_pr_hr(jsp, " [or device number: 0x%x, function "
+ "number: 0x%x]\n", (0x1f & (ip[1] >> 3)),
+ 0x7 & ip[1]);
} else
- printf(" >>>> unexpected protocol identifier: %s\n"
- " with Protocol specific port "
- "identifier\n",
- sg_get_trans_proto_str(p_id, sizeof(b), b));
+ sgj_pr_hr(jsp, " >>>> unexpected protocol identifier: "
+ "%s\n with Protocol specific port "
+ "identifier\n", sg_get_trans_proto_str(p_id, dlen,
+ d));
break;
case 0xa: /* UUID identifier [spc5r08] RFC 4122 */
if (1 != c_set) {
@@ -1648,13 +1638,14 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len, int do_hex,
hex2stderr(ip, i_len, 0);
break;
}
- printf(" Locally assigned UUID: ");
+ n = 0;
+ n += sg_scnpr(b + n, blen - n, " Locally assigned UUID: ");
for (m = 0; m < 16; ++m) {
if ((4 == m) || (6 == m) || (8 == m) || (10 == m))
- printf("-");
- printf("%02x", (unsigned int)ip[2 + m]);
+ n += sg_scnpr(b + n, blen - n, "-");
+ n += sg_scnpr(b + n, blen - n, "%02x", ip[2 + m]);
}
- printf("\n");
+ sgj_pr_hr(jsp, "%s\n", b);
break;
default: /* reserved */
pr2serr(" reserved designator=0x%x\n", desig_type);
@@ -1963,75 +1954,6 @@ export_dev_ids(uint8_t * buff, int len, int verbose)
"around offset=%d\n", off);
}
-/* VPD_EXT_INQ Extended Inquiry [0x86] */
-static void
-decode_x_inq_vpd(uint8_t * buff, int len, int do_hex)
-{
- if (len < 7) {
- pr2serr("Extended INQUIRY data VPD page length too short=%d\n", len);
- return;
- }
- if (do_hex) {
- hex2stdout(buff, len, (1 == do_hex) ? 0 : -1);
- return;
- }
- printf(" ACTIVATE_MICROCODE=%d SPT=%d GRD_CHK=%d APP_CHK=%d "
- "REF_CHK=%d\n", ((buff[4] >> 6) & 0x3), ((buff[4] >> 3) & 0x7),
- !!(buff[4] & 0x4), !!(buff[4] & 0x2), !!(buff[4] & 0x1));
- printf(" UASK_SUP=%d GROUP_SUP=%d PRIOR_SUP=%d HEADSUP=%d ORDSUP=%d "
- "SIMPSUP=%d\n", !!(buff[5] & 0x20), !!(buff[5] & 0x10),
- !!(buff[5] & 0x8), !!(buff[5] & 0x4), !!(buff[5] & 0x2),
- !!(buff[5] & 0x1));
- /* CRD_SUP made obsolete in spc5r04 */
- printf(" WU_SUP=%d [CRD_SUP=%d] NV_SUP=%d V_SUP=%d\n",
- !!(buff[6] & 0x8), !!(buff[6] & 0x4), !!(buff[6] & 0x2),
- !!(buff[6] & 0x1));
- /* NO_PI_CHK and HSSRELEF added in spc5r02 */
- printf(" NO_PI_CHK=%d P_I_I_SUP=%d LUICLR=%d\n", !!(buff[7] & 0x20),
- !!(buff[7] & 0x10), !!(buff[7] & 0x1));
- /* RTD_SUP added in spc5r11, LU_COLL_TYPE added in spc5r09,
- * HSSRELEF added in spc5r02; CBCS obsolete in spc5r01 */
- printf(" LU_COLL_TYPE=%d R_SUP=%d RTD_SUP=%d HSSRELEF=%d [CBCS=%d]\n",
- (buff[8] >> 5) & 0x7, !!(buff[8] & 0x10), !!(buff[8] & 0x8),
- !!(buff[8] & 0x2), !!(buff[8] & 0x1));
- printf(" Multi I_T nexus microcode download=%d\n", buff[9] & 0xf);
- printf(" Extended self-test completion minutes=%d\n",
- sg_get_unaligned_be16(buff + 10)); /* spc4r27 */
- printf(" POA_SUP=%d HRA_SUP=%d VSA_SUP=%d DMS_VALID=%d\n",
- !!(buff[12] & 0x80), !!(buff[12] & 0x40), !!(buff[12] & 0x20),
- !!(buff[12] & 0x10)); /* spc5r20 */
- printf(" Maximum supported sense data length=%d\n",
- buff[13]); /* spc4r34 */
- /* All byte 14 bits added in spc5r09 */
- printf(" IBS=%d IAS=%d SAC=%d NRD1=%d NRD0=%d\n",
- !!(buff[14] & 0x80), !!(buff[14] & 0x40), !!(buff[14] & 0x4),
- !!(buff[14] & 0x2), !!(buff[14] & 0x1));
- printf(" Maximum inquiry change logs=%u\n",
- sg_get_unaligned_be16(buff + 15)); /* spc5r17 */
- printf(" Maximum mode page change logs=%u\n",
- sg_get_unaligned_be16(buff + 17)); /* spc5r17 */
- printf(" DM_MD_4=%d DM_MD_5=%d DM_MD_6=%d DM_MD_7=%d\n",
- !!(buff[19] & 0x80), !!(buff[19] & 0x40), !!(buff[19] & 0x20),
- !!(buff[19] & 0x10)); /* spc5r20 */
- printf(" DM_MD_D=%d DM_MD_E=%d DM_MD_F=%d\n",
- !!(buff[19] & 0x8), !!(buff[19] & 0x4), !!(buff[19] & 0x2));
-}
-
-/* VPD_SOFTW_INF_ID [0x84] */
-static void
-decode_softw_inf_id(uint8_t * buff, int len, int do_hex)
-{
- if (do_hex) {
- hex2stdout(buff, len, (1 == do_hex) ? 0 : -1);
- return;
- }
- len -= 4;
- buff += 4;
- for ( ; len > 5; len -= 6, buff += 6)
- printf(" IEEE identifier: 0x%" PRIx64 "\n",
- sg_get_unaligned_be48(buff + 0));
-}
-
/* VPD_ATA_INFO [0x89] */
static void
decode_ata_info_vpd(uint8_t * buff, int len, int do_hex)
@@ -2091,35 +2013,6 @@ decode_ata_info_vpd(uint8_t * buff, int len, int do_hex)
sg_is_big_endian());
}
-/* VPD_POWER_CONDITION [0x8a] */
-static void
-decode_power_condition(uint8_t * buff, int len, int do_hex)
-{
- if (len < 18) {
- pr2serr("Power condition VPD page length too short=%d\n", len);
- return;
- }
- if (do_hex) {
- hex2stdout(buff, len, (1 == do_hex) ? 0 : -1);
- return;
- }
- printf(" Standby_y=%d Standby_z=%d Idle_c=%d Idle_b=%d Idle_a=%d\n",
- !!(buff[4] & 0x2), !!(buff[4] & 0x1),
- !!(buff[5] & 0x4), !!(buff[5] & 0x2), !!(buff[5] & 0x1));
- printf(" Stopped condition recovery time (ms) %d\n",
- sg_get_unaligned_be16(buff + 6));
- printf(" Standby_z condition recovery time (ms) %d\n",
- sg_get_unaligned_be16(buff + 8));
- printf(" Standby_y condition recovery time (ms) %d\n",
- sg_get_unaligned_be16(buff + 10));
- printf(" Idle_a condition recovery time (ms) %d\n",
- sg_get_unaligned_be16(buff + 12));
- printf(" Idle_b condition recovery time (ms) %d\n",
- sg_get_unaligned_be16(buff + 14));
- printf(" Idle_c condition recovery time (ms) %d\n",
- sg_get_unaligned_be16(buff + 16));
-}
-
/* VPD_SCSI_FEATURE_SETS [0x92] (sfs) */
static void
decode_feature_sets_vpd(uint8_t * buff, int len,
@@ -2779,7 +2672,7 @@ std_inq_decode(const struct opts_t * op, int act_len)
char buff[48];
const uint8_t * rp;
- rp = rsp_buff;
+ rp = rsp_buff + (op->inhex_fn ? op->inhex_off : 0);
memset(vdesc_arr, 0, sizeof(vdesc_arr));
if (op->do_raw) {
dStrRaw((const char *)rp, act_len);
@@ -2940,7 +2833,7 @@ std_inq_decode(const struct opts_t * op, int act_len)
}
}
if (! op->do_export) {
- if ((0 == op->resp_len) && usn_buff[0])
+ if ((0 == op->maxlen) && usn_buff[0])
printf(" Unit serial number: %s\n", usn_buff);
if (op->do_descriptors) {
if (0 == vdesc_arr[0])
@@ -3112,7 +3005,7 @@ std_inq_process(int sg_fd, const struct opts_t * op, int inhex_len)
std_inq_decode(op, inhex_len);
return 0;
}
- rlen = (op->resp_len > 0) ? op->resp_len : SAFE_STD_INQ_RESP_LEN;
+ rlen = (op->maxlen > 0) ? op->maxlen : SAFE_STD_INQ_RESP_LEN;
vb = op->verbose;
res = sg_ll_inquiry_v2(sg_fd, false, 0, rsp_buff, rlen, DEF_PT_TIMEOUT,
&resid, false, vb);
@@ -3123,7 +3016,7 @@ std_inq_process(int sg_fd, const struct opts_t * op, int inhex_len)
}
len = rsp_buff[4] + 5;
if ((len > SAFE_STD_INQ_RESP_LEN) && (len < 256) &&
- (0 == op->resp_len)) {
+ (0 == op->maxlen)) {
rlen = len;
memset(rsp_buff, 0, rlen);
if (sg_ll_inquiry_v2(sg_fd, false, 0, rsp_buff, rlen,
@@ -3137,7 +3030,7 @@ std_inq_process(int sg_fd, const struct opts_t * op, int inhex_len)
len = rsp_buff[4] + 5;
}
}
- if (op->resp_len > 0)
+ if (op->maxlen > 0)
act_len = rlen;
else
act_len = (rlen < len) ? rlen : len;
@@ -3146,7 +3039,7 @@ std_inq_process(int sg_fd, const struct opts_t * op, int inhex_len)
act_len = rlen - resid;
if (act_len < SAFE_STD_INQ_RESP_LEN)
rsp_buff[act_len] = '\0';
- if ((! op->do_only) && (! op->do_export) && (0 == op->resp_len)) {
+ if ((! op->do_only) && (! op->do_export) && (0 == op->maxlen)) {
if (fetch_unit_serial_num(sg_fd, usn_buff, sizeof(usn_buff), vb))
usn_buff[0] = '\0';
}
@@ -3229,13 +3122,13 @@ cmddt_process(int sg_fd, const struct opts_t * op)
}
}
else {
- res = sg_ll_inquiry(sg_fd, true /* cmddt */, false, op->page_num,
+ res = sg_ll_inquiry(sg_fd, true /* cmddt */, false, op->vpd_pn,
rsp_buff, DEF_ALLOC_LEN, true, op->verbose);
if (0 == res) {
peri_type = rsp_buff[0] & PDT_MASK;
if (! op->do_raw) {
- printf("CmdDt INQUIRY, opcode=0x%.2x: [", op->page_num);
- sg_get_opcode_name((uint8_t)op->page_num, peri_type,
+ printf("CmdDt INQUIRY, opcode=0x%.2x: [", op->vpd_pn);
+ sg_get_opcode_name((uint8_t)op->vpd_pn, peri_type,
sizeof(op_name) - 1, op_name);
op_name[sizeof(op_name) - 1] = '\0';
printf("%s]\n", op_name);
@@ -3282,13 +3175,13 @@ cmddt_process(int sg_fd, const struct opts_t * op)
}
} else if (SG_LIB_CAT_ILLEGAL_REQ != res) {
if (! op->do_raw) {
- printf("CmdDt INQUIRY, opcode=0x%.2x: [", op->page_num);
- sg_get_opcode_name((uint8_t)op->page_num, 0,
+ printf("CmdDt INQUIRY, opcode=0x%.2x: [", op->vpd_pn);
+ sg_get_opcode_name((uint8_t)op->vpd_pn, 0,
sizeof(op_name) - 1, op_name);
op_name[sizeof(op_name) - 1] = '\0';
printf("%s]\n", op_name);
}
- pr2serr("CmdDt INQUIRY on opcode=0x%.2x: failed\n", op->page_num);
+ pr2serr("CmdDt INQUIRY on opcode=0x%.2x: failed\n", op->vpd_pn);
}
}
return res;
@@ -3318,9 +3211,9 @@ vpd_mainly_hex(int sg_fd, const struct opts_t * op, int inhex_len)
const char * cp;
uint8_t * rp;
- rp = rsp_buff;
+ rp = rsp_buff + (op->inhex_fn ? op->inhex_off : 0);
if ((! op->do_raw) && (op->do_hex < 2))
- printf("VPD INQUIRY, page code=0x%.2x:\n", op->page_num);
+ printf("VPD INQUIRY, page code=0x%.2x:\n", op->vpd_pn);
if (sg_fd < 0) {
len = sg_get_unaligned_be16(rp + 2) + 4;
if (op->verbose && (len > inhex_len))
@@ -3329,14 +3222,14 @@ vpd_mainly_hex(int sg_fd, const struct opts_t * op, int inhex_len)
res = 0;
} else {
memset(rp, 0, DEF_ALLOC_LEN);
- res = vpd_fetch_page_from_dev(sg_fd, rp, op->page_num, op->resp_len,
+ res = vpd_fetch_page_from_dev(sg_fd, rp, op->vpd_pn, op->maxlen,
op->verbose, &len);
}
if (0 == res) {
if (op->do_raw)
dStrRaw((const char *)rp, len);
else {
- if (0 == op->page_num)
+ if (0 == op->vpd_pn)
decode_supported_vpd(rp, len, op->do_hex);
else {
if (op->verbose) {
@@ -3361,18 +3254,25 @@ vpd_mainly_hex(int sg_fd, const struct opts_t * op, int inhex_len)
/* Returns 0 if successful */
static int
-vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len)
+vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int inhex_len)
{
bool bad = false;
- int len, pdt, pn, vb, mxlen;
+ int len, pdt, pn, vb, mxlen /*, pqual */;
int res = 0;
+ sgj_state * jsp = &op->json_st;
+ bool as_json = jsp->pr_as_json;
+ sgj_opaque_p jo2p = NULL;
+ sgj_opaque_p jap = NULL;
+ const char * np;
+ // const char * pdt_str;
uint8_t * rp;
+ // char d[80];
- pn = op->page_num;
- rp = rsp_buff;
+ pn = op->vpd_pn;
+ rp = rsp_buff + (op->inhex_fn ? op->inhex_off : 0);
vb = op->verbose;
if (sg_fd >= 0)
- mxlen = op->resp_len;
+ mxlen = op->maxlen;
else
mxlen = inhex_len;
if (sg_fd != -1 && !op->do_force && pn != VPD_SUPPORTED_VPDS) {
@@ -3400,7 +3300,7 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len)
else if (op->do_hex)
hex2stdout(rp, len, (1 == op->do_hex) ? 0 : -1);
else
- decode_supported_vpd(rp, len, PDT_MASK & rp[0]);
+ decode_supported_vpd(rp, len, op->do_hex);
break;
case VPD_UNIT_SERIAL_NUM:
if (! op->do_raw && ! op->do_export && (op->do_hex < 2))
@@ -3445,8 +3345,9 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len)
}
break;
case VPD_DEVICE_ID:
+ np = "Device Identification VPD page";
if (! op->do_raw && ! op->do_export && (op->do_hex < 3))
- printf("VPD INQUIRY: Device Identification page\n");
+ sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page_from_dev(sg_fd, rp, pn, mxlen, vb, &len);
if (res)
break;
@@ -3454,54 +3355,88 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len)
dStrRaw((const char *)rp, len);
else if (op->do_hex > 2)
hex2stdout(rp, len, -1);
- else if (op->do_export)
+ else if (op->do_export && (! as_json))
export_dev_ids(rp + 4, len - 4, op->verbose);
- else
- decode_id_vpd(rp, len, op->do_hex, op->verbose);
+ else {
+ if (as_json) {
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ jap = sgj_new_named_array(jsp, jo2p,
+ "designation_descriptor_list");
+ }
+ decode_id_vpd(rp, len, op, jap);
+ }
break;
- case VPD_SOFTW_INF_ID:
+ case VPD_SOFTW_INF_ID: /* 0x84 ["sii"] */
+ np = "Software interface identification VPD page";
if (! op->do_raw && (op->do_hex < 2))
- printf("VPD INQUIRY: Software interface identification page\n");
+ printf("VPD INQUIRY: %s\n", np);
res = vpd_fetch_page_from_dev(sg_fd, rp, pn, mxlen, vb, &len);
if (res)
break;
if (op->do_raw)
dStrRaw((const char *)rp, len);
- else
- decode_softw_inf_id(rp, len, op->do_hex);
+ else {
+ if (as_json) {
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ jap = sgj_new_named_array(jsp, jo2p,
+ "software_interface_identifier_list");
+ }
+ decode_softw_inf_id(rp, len, op, jap);
+ }
break;
- case VPD_MAN_NET_ADDR:
+ case VPD_MAN_NET_ADDR: /* 0x86 ["mna"] */
+ np = "Management network addresses page";
if (!op->do_raw && (op->do_hex < 2))
- printf("VPD INQUIRY: Management network addresses page\n");
+ sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page_from_dev(sg_fd, rp, pn, mxlen, vb, &len);
if (res)
break;
if (op->do_raw)
dStrRaw((const char *)rp, len);
- else
- decode_net_man_vpd(rp, len, op->do_hex);
+ else {
+ // pdt = rp[0] & PDT_MASK;
+ // pdt_str = sg_get_pdt_str(pdt, sizeof(d), d);
+ // pqual = (rp[0] & 0xe0) >> 5;
+ if (as_json) {
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ jap = sgj_new_named_array(jsp, jo2p,
+ "network_services_descriptor_list");
+ }
+ decode_net_man_vpd(rp, len, op, jap);
+ }
break;
case VPD_MODE_PG_POLICY:
+ np = "Mode page policy";
if (!op->do_raw && (op->do_hex < 2))
- printf("VPD INQUIRY: Mode page policy\n");
+ sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page_from_dev(sg_fd, rp, pn, mxlen, vb, &len);
if (res)
break;
if (op->do_raw)
dStrRaw((const char *)rp, len);
- else
- decode_mode_policy_vpd(rp, len, op->do_hex);
+ else {
+ if (as_json) {
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ jap = sgj_new_named_array(jsp, jo2p,
+ "mode_page_policy_descriptor_list");
+ }
+ decode_mode_policy_vpd(rp, len, op, jap);
+ }
break;
case VPD_EXT_INQ:
+ np = "Extended INQUIRY data";
if (!op->do_raw && (op->do_hex < 2))
- printf("VPD INQUIRY: extended INQUIRY data page\n");
+ sgj_pr_hr(jsp, "VPD INQUIRY: %s page\n", np);
res = vpd_fetch_page_from_dev(sg_fd, rp, pn, mxlen, vb, &len);
if (res)
break;
if (op->do_raw)
dStrRaw((const char *)rp, len);
- else
- decode_x_inq_vpd(rp, len, op->do_hex);
+ else {
+ if (as_json)
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ decode_x_inq_vpd(rp, len, false /* protect */, op, jo2p);
+ }
break;
case VPD_ATA_INFO:
if (!op->do_raw && (op->do_hex < 2))
@@ -3518,16 +3453,20 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len)
else
decode_ata_info_vpd(rp, len, op->do_hex);
break;
- case VPD_POWER_CONDITION:
+ case VPD_POWER_CONDITION: /* 0x8a ["pc"] */
+ np = "Power condition page VPD page";
if (!op->do_raw && (op->do_hex < 2))
- printf("VPD INQUIRY: Power condition page\n");
+ sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page_from_dev(sg_fd, rp, pn, mxlen, vb, &len);
if (res)
break;
if (op->do_raw)
dStrRaw((const char *)rp, len);
- else
- decode_power_condition(rp, len, op->do_hex);
+ else {
+ if (as_json)
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ decode_power_condition(rp, len, op, jo2p);
+ }
break;
case VPD_SCSI_FEATURE_SETS: /* 0x92 */
if (!op->do_raw && (op->do_hex < 2))
@@ -3671,15 +3610,22 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len)
decode_rdac_vpd_c9(rp, len, op->do_hex);
break;
case VPD_SCSI_PORTS:
+ np = "SCSI Ports VPD page";
if (!op->do_raw && (op->do_hex < 2))
- printf("VPD INQUIRY: SCSI Ports page\n");
+ sgj_pr_hr(jsp, "VPD INQUIRY: %s\n", np);
res = vpd_fetch_page_from_dev(sg_fd, rp, pn, mxlen, vb, &len);
if (res)
break;
if (op->do_raw)
dStrRaw((const char *)rp, len);
- else
- decode_scsi_ports_vpd(rp, len, op->do_hex, op->verbose);
+ else {
+ if (as_json) {
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ jap = sgj_new_named_array(jsp, jo2p,
+ "scsi_ports_descriptor_list");
+ }
+ decode_scsi_ports_vpd(rp, len, op, jap);
+ }
break;
default:
bad = true;
@@ -4093,17 +4039,21 @@ err_out:
int
main(int argc, char * argv[])
{
+ bool as_json;
int res, n, err;
int sg_fd = -1;
int ret = 0;
int inhex_len = 0;
const struct svpd_values_name_t * vnp;
+ sgj_state * jsp;
+ sgj_opaque_p jop = NULL;
struct opts_t opts;
struct opts_t * op;
op = &opts;
memset(op, 0, sizeof(opts));
- op->page_num = -1;
+ op->invoker = SG_VPD_INV_SG_INQ;
+ op->vpd_pn = -1;
op->page_pdt = -1;
op->do_block = -1; /* use default for OS */
res = parse_cmd_line(op, argc, argv);
@@ -4138,25 +4088,25 @@ main(int argc, char * argv[])
pr2serr("Version string: %s\n", version_str);
return 0;
}
- if (op->page_arg) {
- if (op->page_num >= 0) {
+ if (op->page_str) {
+ if (op->vpd_pn >= 0) {
pr2serr("Given '-p' option and another option that "
"implies a page\n");
return SG_LIB_CONTRADICT;
}
- if (isalpha((uint8_t)op->page_arg[0])) {
- vnp = sdp_find_vpd_by_acron(op->page_arg);
+ if (isalpha((uint8_t)op->page_str[0])) {
+ vnp = sdp_find_vpd_by_acron(op->page_str);
if (NULL == vnp) {
#ifdef SG_SCSI_STRINGS
if (op->opt_new)
pr2serr("abbreviation %s given to '--page=' "
- "not recognized\n", op->page_arg);
+ "not recognized\n", op->page_str);
else
pr2serr("abbreviation %s given to '-p=' "
- "not recognized\n", op->page_arg);
+ "not recognized\n", op->page_str);
#else
pr2serr("abbreviation %s given to '--page=' "
- "not recognized\n", op->page_arg);
+ "not recognized\n", op->page_str);
#endif
pr2serr(">>> Available abbreviations:\n");
enumerate_vpds();
@@ -4164,14 +4114,14 @@ main(int argc, char * argv[])
}
if ((1 != op->do_hex) && (0 == op->do_raw))
op->do_decode = true;
- op->page_num = vnp->value;
+ op->vpd_pn = vnp->value;
op->page_pdt = vnp->pdt;
- } else if ('-' == op->page_arg[0])
- op->page_num = VPD_NOPE_WANT_STD_INQ;
+ } else if ('-' == op->page_str[0])
+ op->vpd_pn = VPD_NOPE_WANT_STD_INQ;
else {
#ifdef SG_SCSI_STRINGS
if (op->opt_new) {
- n = sg_get_num(op->page_arg);
+ n = sg_get_num(op->page_str);
if ((n < 0) || (n > 255)) {
pr2serr("Bad argument to '--page=', "
"expecting 0 to 255 inclusive\n");
@@ -4184,7 +4134,7 @@ main(int argc, char * argv[])
int num;
unsigned int u;
- num = sscanf(op->page_arg, "%x", &u);
+ num = sscanf(op->page_str, "%x", &u);
if ((1 != num) || (u > 255)) {
pr2serr("Inappropriate value after '-o=' "
"or '-p=' option\n");
@@ -4194,7 +4144,7 @@ main(int argc, char * argv[])
n = u;
}
#else
- n = sg_get_num(op->page_arg);
+ n = sg_get_num(op->page_str);
if ((n < 0) || (n > 255)) {
pr2serr("Bad argument to '--page=', "
"expecting 0 to 255 inclusive\n");
@@ -4204,9 +4154,14 @@ main(int argc, char * argv[])
if ((1 != op->do_hex) && (0 == op->do_raw))
op->do_decode = true;
#endif /* SG_SCSI_STRINGS */
- op->page_num = n;
+ op->vpd_pn = n;
}
}
+ jsp = &op->json_st;
+ as_json = jsp->pr_as_json;
+ if (as_json)
+ jop = sgj_start(MY_NAME, version_str, argc, argv, jsp);
+
rsp_buff = sg_memalign(rsp_buff_sz, 0 /* page align */, &free_rsp_buff,
false);
if (NULL == rsp_buff) {
@@ -4233,7 +4188,8 @@ main(int argc, char * argv[])
goto err_out;
}
op->do_raw = 0; /* don't want raw on output with --inhex= */
- if (-1 == op->page_num) { /* may be able to deduce VPD page */
+ op->inhex_off = 0;
+ if (-1 == op->vpd_pn) { /* may be able to deduce VPD page */
if (op->page_pdt < 0)
op->page_pdt = PDT_MASK & rsp_buff[0];
if ((0x2 == (0xf & rsp_buff[3])) && (rsp_buff[2] > 2)) {
@@ -4260,7 +4216,7 @@ main(int argc, char * argv[])
if (op->verbose)
pr2serr("Guessing from --inhex= this is VPD "
"page 0x%x\n", rsp_buff[1]);
- op->page_num = rsp_buff[1];
+ op->vpd_pn = rsp_buff[1];
op->do_vpd = true;
if ((1 != op->do_hex) && (0 == op->do_raw))
op->do_decode = true;
@@ -4270,6 +4226,12 @@ main(int argc, char * argv[])
pr2serr("page number unclear from --inhex, hope it's a "
"standard INQUIRY\n");
}
+ } else
+ op->do_vpd = true;
+ if (op->do_vpd) { /* Allow for multiple VPD pages from 'sg_vpd -a' */
+ op->maxlen = inhex_len;
+ ret = svpd_inhex_decode_all(op, jop);
+ goto fini2;
}
} else if (0 == op->device_name) {
pr2serr("No DEVICE argument given\n\n");
@@ -4277,13 +4239,13 @@ main(int argc, char * argv[])
ret = SG_LIB_SYNTAX_ERROR;
goto err_out;
}
- if (VPD_NOPE_WANT_STD_INQ == op->page_num)
- op->page_num = -1; /* now past guessing, set to normal indication */
+ if (VPD_NOPE_WANT_STD_INQ == op->vpd_pn)
+ op->vpd_pn = -1; /* now past guessing, set to normal indication */
if (op->do_export) {
- if (op->page_num != -1) {
- if (op->page_num != VPD_DEVICE_ID &&
- op->page_num != VPD_UNIT_SERIAL_NUM) {
+ if (op->vpd_pn != -1) {
+ if (op->vpd_pn != VPD_DEVICE_ID &&
+ op->vpd_pn != VPD_UNIT_SERIAL_NUM) {
pr2serr("Option '--export' only supported for VPD pages 0x80 "
"and 0x83\n");
usage_for(op);
@@ -4295,7 +4257,7 @@ main(int argc, char * argv[])
}
}
- if ((0 == op->do_cmddt) && (op->page_num >= 0) && op->page_given)
+ if ((0 == op->do_cmddt) && (op->vpd_pn >= 0) && op->page_given)
op->do_vpd = true;
if (op->do_raw && op->do_hex) {
@@ -4317,8 +4279,8 @@ main(int argc, char * argv[])
ret = SG_LIB_CONTRADICT;
goto err_out;
}
- if (((op->do_vpd || op->do_cmddt)) && (op->page_num < 0))
- op->page_num = 0;
+ if (((op->do_vpd || op->do_cmddt)) && (op->vpd_pn < 0))
+ op->vpd_pn = 0;
if (op->num_pages > 1) {
pr2serr("Can only fetch one page (VPD or Cmd) at a time\n");
usage_for(op);
@@ -4326,7 +4288,7 @@ main(int argc, char * argv[])
goto err_out;
}
if (op->do_descriptors) {
- if ((op->resp_len > 0) && (op->resp_len < 60)) {
+ if ((op->maxlen > 0) && (op->maxlen < 60)) {
pr2serr("version descriptors need INQUIRY response "
"length >= 60 bytes\n");
ret = SG_LIB_SYNTAX_ERROR;
@@ -4354,7 +4316,7 @@ main(int argc, char * argv[])
if (op->inhex_fn) {
if (op->do_vpd) {
if (op->do_decode)
- ret = vpd_decode(-1, op, inhex_len);
+ ret = vpd_decode(-1, op, jop, inhex_len);
else
ret = vpd_mainly_hex(-1, op, inhex_len);
goto err_out;
@@ -4445,14 +4407,14 @@ main(int argc, char * argv[])
if (ret)
goto err_out;
} else if (op->do_cmddt) {
- if (op->page_num < 0)
- op->page_num = 0;
+ if (op->vpd_pn < 0)
+ op->vpd_pn = 0;
ret = cmddt_process(sg_fd, op);
if (ret)
goto err_out;
} else if (op->do_vpd) {
if (op->do_decode) {
- ret = vpd_decode(sg_fd, op, -1);
+ ret = vpd_decode(sg_fd, op, jop, -1);
if (ret)
goto err_out;
} else {
@@ -4482,9 +4444,15 @@ err_out:
if (res < 0) {
pr2serr("close error: %s\n", safe_strerror(-res));
if (0 == ret)
- return sg_convert_errno(-res);
+ ret = sg_convert_errno(-res);
}
- return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
+ ret = (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
+ if (as_json) {
+ if (0 == op->do_hex)
+ sgj_pr2file(jsp, NULL, ret, stdout);
+ sgj_finish(jsp);
+ }
+ return ret;
}
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 89c982e4..122111d2 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -31,7 +31,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-#include "sg_vpd.h"
+#include "sg_vpd_common.h" /* shared with sg_inq */
/* This utility program was originally written for the Linux OS SCSI subsystem.
@@ -42,49 +42,9 @@
*/
-static const char * version_str = "1.73 20220705"; /* spc6r06 + sbc5r01 */
-
-#define MY_NAME "sg_decode_sense"
-
-/* standard VPD pages, in ascending page number order */
-#define VPD_SUPPORTED_VPDS 0x0
-#define VPD_UNIT_SERIAL_NUM 0x80
-#define VPD_IMP_OP_DEF 0x81 /* obsolete in SPC-2 */
-#define VPD_ASCII_OP_DEF 0x82 /* obsolete in SPC-2 */
-#define VPD_DEVICE_ID 0x83
-#define VPD_SOFTW_INF_ID 0x84
-#define VPD_MAN_NET_ADDR 0x85
-#define VPD_EXT_INQ 0x86 /* Extended Inquiry */
-#define VPD_MODE_PG_POLICY 0x87
-#define VPD_SCSI_PORTS 0x88
-#define VPD_ATA_INFO 0x89
-#define VPD_POWER_CONDITION 0x8a
-#define VPD_DEVICE_CONSTITUENTS 0x8b
-#define VPD_CFA_PROFILE_INFO 0x8c
-#define VPD_POWER_CONSUMPTION 0x8d
-#define VPD_3PARTY_COPY 0x8f /* 3PC, XCOPY, SPC-4, SBC-3 */
-#define VPD_PROTO_LU 0x90
-#define VPD_PROTO_PORT 0x91
-#define VPD_SCSI_FEATURE_SETS 0x92 /* spc5r11 */
-#define VPD_BLOCK_LIMITS 0xb0 /* SBC-3 */
-#define VPD_SA_DEV_CAP 0xb0 /* SSC-3 */
-#define VPD_OSD_INFO 0xb0 /* OSD */
-#define VPD_BLOCK_DEV_CHARS 0xb1 /* SBC-3 */
-#define VPD_MAN_ASS_SN 0xb1 /* SSC-3, ADC-2 */
-#define VPD_SECURITY_TOKEN 0xb1 /* OSD */
-#define VPD_TA_SUPPORTED 0xb2 /* SSC-3 */
-#define VPD_LB_PROVISIONING 0xb2 /* SBC-3 */
-#define VPD_REFERRALS 0xb3 /* SBC-3 */
-#define VPD_AUTOMATION_DEV_SN 0xb3 /* SSC-3 */
-#define VPD_SUP_BLOCK_LENS 0xb4 /* sbc4r01 */
-#define VPD_DTDE_ADDRESS 0xb4 /* SSC-4 */
-#define VPD_BLOCK_DEV_C_EXTENS 0xb5 /* sbc4r02 */
-#define VPD_LB_PROTECTION 0xb5 /* SSC-5 */
-#define VPD_ZBC_DEV_CHARS 0xb6 /* zbc-r01b */
-#define VPD_BLOCK_LIMITS_EXT 0xb7 /* sbc4r08 */
-#define VPD_FORMAT_PRESETS 0xb8 /* sbc4r18 */
-#define VPD_CON_POS_RANGE 0xb9 /* sbc5r01 */
-#define VPD_NOPE_WANT_STD_INQ -2 /* request for standard inquiry */
+static const char * version_str = "1.74 20220711"; /* spc6r06 + sbc5r01 */
+
+#define MY_NAME "sg_vpd"
/* Device identification VPD page associations */
#define VPD_ASSOC_LU 0
@@ -118,7 +78,6 @@ static int svpd_unable_to_decode(int sg_fd, struct opts_t * op, int subvalue,
static int filter_dev_ids(const char * print_if_found, int num_leading,
uint8_t * buff, int len, int m_assoc,
- int m_desig_type, int m_code_set,
struct opts_t * op, sgj_opaque_p jop);
static const int rsp_buff_sz = MX_ALLOC_LEN + 2;
@@ -450,20 +409,7 @@ static const char * sg_ansi_version_arr[16] =
"reserved [Fh]",
};
-static const char *
-pqual_str(int pqual)
-{
- switch (pqual) {
- case 0:
- return "LU accessible";
- case 1:
- return "LU temporarily unavailable";
- case 3:
- return "LU not accessible via this port";
- default:
- return "value reserved by T10";
- }
-}
+static const char * vpd_p_s = "VPD page";
static const char *
hot_pluggable_str(int hp)
@@ -569,49 +515,49 @@ skip1:
pqual_str(pqual));
sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_device_type", pdt, NULL,
sg_get_pdt_str(pdt, clen, c));
- sgj_add_nv_ihex_ane(jsp, jo2p, "rmb", !!(b[1] & 0x80), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "rmb", !!(b[1] & 0x80), false,
"Removable Medium Bit");
- sgj_add_nv_ihex_ane(jsp, jo2p, "lu_cong", !!(b[1] & 0x40), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "lu_cong", !!(b[1] & 0x40), false,
"Logical Unit Conglomerate");
sgj_add_nv_ihexstr(jsp, jo2p, "hot_pluggable", hp, NULL,
hot_pluggable_str(hp));
snprintf(c, clen, "%s", (ver > 0xf) ? "old or reserved version code" :
sg_ansi_version_arr[ver]);
sgj_add_nv_ihexstr(jsp, jo2p, "version", ver, NULL, c);
- sgj_add_nv_ihex_ane(jsp, jo2p, "aerc", !!(b[3] & 0x80), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "aerc", !!(b[3] & 0x80), false,
"Asynchronous Event Reporting Capability (obsolete "
"SPC-3)");
- sgj_add_nv_ihex_ane(jsp, jo2p, "trmtsk", !!(b[3] & 0x40), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "trmtsk", !!(b[3] & 0x40), false,
"Terminate Task (obsolete SPC-2)");
- sgj_add_nv_ihex_ane(jsp, jo2p, "normaca", !!(b[3] & 0x20), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "normaca", !!(b[3] & 0x20), false,
"Normal ACA (Auto Contingent Allegiance)");
- sgj_add_nv_ihex_ane(jsp, jo2p, "hisup", !!(b[3] & 0x10), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "hisup", !!(b[3] & 0x10), false,
"Hierarchial Support");
sgj_add_nv_ihex(jsp, jo2p, "response_data_format", b[3] & 0xf);
- sgj_add_nv_ihex_ane(jsp, jo2p, "sccs", !!(b[5] & 0x80), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "sccs", !!(b[5] & 0x80), false,
"SCC (SCSI Storage Commands) Supported");
- sgj_add_nv_ihex_ane(jsp, jo2p, "acc", !!(b[5] & 0x40), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "acc", !!(b[5] & 0x40), false,
"Access Commands Coordinator (obsolete SPC-5)");
tpgs = (b[5] >> 4) & 0x3;
- sgj_add_nv_ihexstr_ane(jsp, jo2p, "tpgs", tpgs, false, NULL,
+ sgj_add_nv_ihexstr_nex(jsp, jo2p, "tpgs", tpgs, false, NULL,
tpgs_str(tpgs), "Target Port Group Support");
- sgj_add_nv_ihex_ane(jsp, jo2p, "3pc", !!(b[5] & 0x8), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "3pc", !!(b[5] & 0x8), false,
"Third Party Copy");
sgj_add_nv_ihex(jsp, jo2p, "protect", !!(b[5] & 0x1));
/* Skip SPI specific flags which have been obsolete for a while) */
- sgj_add_nv_ihex_ane(jsp, jo2p, "bque", !!(b[6] & 0x80), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "bque", !!(b[6] & 0x80), false,
"Basic task management model (obsolete SPC-4)");
- sgj_add_nv_ihex_ane(jsp, jo2p, "encserv", !!(b[6] & 0x40), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "encserv", !!(b[6] & 0x40), false,
"Enclousure Services supported");
- sgj_add_nv_ihex_ane(jsp, jo2p, "multip", !!(b[6] & 0x10), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "multip", !!(b[6] & 0x10), false,
"Multiple SCSI port");
- sgj_add_nv_ihex_ane(jsp, jo2p, "mchngr", !!(b[6] & 0x8), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "mchngr", !!(b[6] & 0x8), false,
"Medium changer (obsolete SPC-4)");
- sgj_add_nv_ihex_ane(jsp, jo2p, "reladr", !!(b[7] & 0x80), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "reladr", !!(b[7] & 0x80), false,
"Relative Addressing (obsolete in SPC-4)");
- sgj_add_nv_ihex_ane(jsp, jo2p, "linked", !!(b[7] & 0x8), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "linked", !!(b[7] & 0x8), false,
"Linked Commands (obsolete in SPC-4)");
- sgj_add_nv_ihex_ane(jsp, jo2p, "cmdque", !!(b[7] & 0x2), false,
+ sgj_add_nv_ihex_nex(jsp, jo2p, "cmdque", !!(b[7] & 0x2), false,
"Command Management Model (command queuing)");
if (len < 16)
return;
@@ -627,11 +573,12 @@ skip1:
sgj_add_nv_s(jsp, jo2p, "product_revision_level", c);
}
+/* VPD_DEVICE_ID 0x83 ["di, di_asis, di_lu, di_port, di_target"] */
static void
device_id_vpd_variants(uint8_t * buff, int len, int subvalue,
struct opts_t * op, sgj_opaque_p jap)
{
- int m_a, m_d, m_cs, blen;
+ int m_a, blen;
uint8_t * b;
if (len < 4) {
@@ -641,155 +588,29 @@ device_id_vpd_variants(uint8_t * buff, int len, int subvalue,
blen = len - 4;
b = buff + 4;
m_a = -1;
- m_d = -1;
- m_cs = -1;
if (0 == subvalue) {
filter_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_LU), 0, b, blen,
- VPD_ASSOC_LU, m_d, m_cs, op, jap);
+ VPD_ASSOC_LU, op, jap);
filter_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TPORT), 0, b, blen,
- VPD_ASSOC_TPORT, m_d, m_cs, op, jap);
+ VPD_ASSOC_TPORT, op, jap);
filter_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TDEVICE), 0, b, blen,
- VPD_ASSOC_TDEVICE, m_d, m_cs, op, jap);
+ VPD_ASSOC_TDEVICE, op, jap);
} else if (VPD_DI_SEL_AS_IS == subvalue)
- filter_dev_ids(NULL, 0, b, blen, m_a, m_d, m_cs, op, jap);
+ filter_dev_ids(NULL, 0, b, blen, m_a, op, jap);
else {
if (VPD_DI_SEL_LU & subvalue)
filter_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_LU), 0, b, blen,
- VPD_ASSOC_LU, m_d, m_cs, op, jap);
+ VPD_ASSOC_LU, op, jap);
if (VPD_DI_SEL_TPORT & subvalue)
filter_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TPORT), 0, b,
- blen, VPD_ASSOC_TPORT, m_d, m_cs, op, jap);
+ blen, VPD_ASSOC_TPORT, op, jap);
if (VPD_DI_SEL_TARGET & subvalue)
filter_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TDEVICE), 0,
- b, blen, VPD_ASSOC_TDEVICE, m_d, m_cs, op, jap);
+ b, blen, VPD_ASSOC_TDEVICE, op, jap);
}
}
-static const char * network_service_type_arr[] =
-{
- "unspecified",
- "storage configuration service",
- "diagnostics",
- "status",
- "logging",
- "code download",
- "copy service",
- "administrative configuration service",
- "reserved[0x8]", "reserved[0x9]",
- "reserved[0xa]", "reserved[0xb]", "reserved[0xc]", "reserved[0xd]",
- "reserved[0xe]", "reserved[0xf]", "reserved[0x10]", "reserved[0x11]",
- "reserved[0x12]", "reserved[0x13]", "reserved[0x14]", "reserved[0x15]",
- "reserved[0x16]", "reserved[0x17]", "reserved[0x18]", "reserved[0x19]",
- "reserved[0x1a]", "reserved[0x1b]", "reserved[0x1c]", "reserved[0x1d]",
- "reserved[0x1e]", "reserved[0x1f]",
-};
-
-/* VPD_MAN_NET_ADDR */
-static void
-decode_net_man_vpd(uint8_t * buff, int len, struct opts_t * op,
- sgj_opaque_p jap)
-{
- int k, bump, na_len, assoc, nst;
- sgj_state * jsp = &op->json_st;
- sgj_opaque_p jo2p;
- uint8_t * bp;
- const char * assoc_str;
- const char * nst_str;
-
- if ((1 == op->do_hex) || (op->do_hex > 2)) {
- hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
- return;
- }
- if (len < 4) {
- pr2serr("Management network addresses VPD page length too short=%d\n",
- len);
- return;
- }
- len -= 4;
- bp = buff + 4;
- for (k = 0; k < len; k += bump, bp += bump) {
- assoc = (bp[0] >> 5) & 0x3;
- assoc_str = sg_get_desig_assoc_str(assoc);
- nst = bp[0] & 0x1f;
- nst_str = network_service_type_arr[nst];
- sgj_pr_hr(jsp, " %s, Service type: %s\n", assoc_str, nst_str);
- na_len = sg_get_unaligned_be16(bp + 2);
- if (jsp->pr_as_json) {
- jo2p = sgj_new_unattached_object(jsp);
- sgj_add_nv_ihexstr(jsp, jo2p, "association", assoc, NULL,
- assoc_str);
- sgj_add_nv_ihexstr(jsp, jo2p, "service_type", nst, NULL,
- nst_str);
- sgj_add_nv_s_len(jsp, jo2p, "network_address",
- (const char *)(bp + 4), na_len);
- sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p);
- }
- if (na_len > 0) {
- if (op->do_hex > 1) {
- printf(" Network address:\n");
- hex2stdout((bp + 4), na_len, 0);
- } else
- sgj_pr_hr(jsp, " %s\n", bp + 4);
- }
- bump = 4 + na_len;
- if ((k + bump) > len) {
- pr2serr("Management network addresses VPD page, short "
- "descriptor length=%d, left=%d\n", bump, (len - k));
- return;
- }
- }
-}
-
-static const char * mode_page_policy_arr[] =
-{
- "shared",
- "per target port",
- "per initiator port",
- "per I_T nexus",
-};
-
-/* VPD_MODE_PG_POLICY */
-static void
-decode_mode_policy_vpd(uint8_t * buff, int len, int do_hex)
-{
- int k, bump;
- uint8_t * bp;
-
- if ((1 == do_hex) || (do_hex > 2)) {
- hex2stdout(buff, len, (1 == do_hex) ? 1 : -1);
- return;
- }
- if (len < 4) {
- pr2serr("Mode page policy VPD page length too short=%d\n", len);
- return;
- }
- len -= 4;
- bp = buff + 4;
- for (k = 0; k < len; k += bump, bp += bump) {
- bump = 4;
- if ((k + bump) > len) {
- pr2serr("Mode page policy VPD page, short "
- "descriptor length=%d, left=%d\n", bump, (len - k));
- return;
- }
- if (do_hex > 1)
- hex2stdout(bp, 4, 1);
- else {
- printf(" Policy page code: 0x%x", (bp[0] & 0x3f));
- if (bp[1])
- printf(", subpage code: 0x%x\n", bp[1]);
- else
- printf("\n");
- if ((0 == k) && (0x3f == (0x3f & bp[0])) && (0xff == bp[1]))
- printf(" therefore the policy applies to all modes pages "
- "and subpages\n");
- printf(" MLUS=%d, Policy: %s\n", !!(bp[2] & 0x80),
- mode_page_policy_arr[bp[2] & 0x3]);
- }
- }
-}
-
-/* VPD_SCSI_PORTS */
+/* VPD_SCSI_PORTS 0x88 ["sp"] */
static void
decode_scsi_ports_vpd(uint8_t * buff, int len, struct opts_t * op,
sgj_opaque_p jap)
@@ -829,6 +650,10 @@ decode_scsi_ports_vpd(uint8_t * buff, int len, struct opts_t * op,
} else {
char b[1024];
+ sg_decode_transportid_str(" ", bp + 8, ip_tid_len,
+ true, sizeof(b), b);
+ if (jsp->pr_as_json)
+ sgj_add_nv_s(jsp, jo2p, "initiator_port_transport_id", b);
sgj_pr_hr(jsp, "%s",
sg_decode_transportid_str(" ", bp + 8,
ip_tid_len, true, sizeof(b), b));
@@ -855,7 +680,7 @@ decode_scsi_ports_vpd(uint8_t * buff, int len, struct opts_t * op,
"designation_descriptor_list");
}
filter_dev_ids("", 2 /* leading spaces */, bp + bump + 4,
- tpd_len, VPD_ASSOC_TPORT, -1, -1, op, ja2p);
+ tpd_len, VPD_ASSOC_TPORT, op, ja2p);
}
}
bump += tpd_len + 4;
@@ -864,10 +689,10 @@ decode_scsi_ports_vpd(uint8_t * buff, int len, struct opts_t * op,
}
/* Prints outs an abridged set of device identification designators
- selected by association, designator type and/or code set. */
+ selected by association, designator type and/or code set. Not used
+ for JSON output. */
static int
-filter_dev_ids_quiet(uint8_t * buff, int len, int m_assoc,
- int m_desig_type, int m_code_set)
+filter_dev_ids_quiet(uint8_t * buff, int len, int m_assoc)
{
int k, m, p_id, c_set, piv, desig_type, i_len, naa, off, u;
int assoc, is_sas, rtp;
@@ -889,8 +714,7 @@ filter_dev_ids_quiet(uint8_t * buff, int len, int m_assoc,
desig_type = 3;
i_len = 16;
} else {
- u = sg_vpd_dev_id_iter(buff, len, &off, m_assoc, m_desig_type,
- m_code_set);
+ u = sg_vpd_dev_id_iter(buff, len, &off, m_assoc, -1, -1);
if (0 != u)
break;
bp = buff + off;
@@ -1061,11 +885,10 @@ filter_dev_ids_quiet(uint8_t * buff, int len, int m_assoc,
}
/* Prints outs designation descriptors (dd_s) selected by association,
- designator type and/or code set. */
+ designator type and/or code set. VPD_DEVICE_ID and VPD_SCSI_PORTS */
static int
filter_dev_ids(const char * print_if_found, int num_leading, uint8_t * buff,
- int len, int m_assoc, int m_desig_type, int m_code_set,
- struct opts_t * op, sgj_opaque_p jap)
+ int len, int m_assoc, struct opts_t * op, sgj_opaque_p jap)
{
bool printed, sgj_out_hr;
int assoc, off, u, i_len;
@@ -1076,8 +899,15 @@ filter_dev_ids(const char * print_if_found, int num_leading, uint8_t * buff,
static const int blen = sizeof(b);
if (op->do_quiet && (! jsp->pr_as_json))
- return filter_dev_ids_quiet(buff, len, m_assoc, m_desig_type,
- m_code_set);
+ return filter_dev_ids_quiet(buff, len, m_assoc);
+ sgj_out_hr = false;
+ if (jsp->pr_as_json) {
+ int ret = filter_json_dev_ids(buff, len, m_assoc, op, jap);
+
+ if (ret || (! jsp->pr_out_hr))
+ return ret;
+ sgj_out_hr = true;
+ }
if (num_leading > (int)(sizeof(sp) - 2))
num_leading = sizeof(sp) - 2;
if (num_leading > 0)
@@ -1093,8 +923,7 @@ filter_dev_ids(const char * print_if_found, int num_leading, uint8_t * buff,
}
off = -1;
printed = false;
- while ((u = sg_vpd_dev_id_iter(buff, len, &off, m_assoc, m_desig_type,
- m_code_set)) == 0) {
+ while ((u = sg_vpd_dev_id_iter(buff, len, &off, m_assoc, -1, -1)) == 0) {
bp = buff + off;
i_len = bp[3];
if ((off + i_len + 4) > len) {
@@ -1102,18 +931,6 @@ filter_dev_ids(const char * print_if_found, int num_leading, uint8_t * buff,
" remaining response length=%d\n", (len - off));
return SG_LIB_CAT_MALFORMED;
}
- sgj_out_hr = false;
- if (jsp->pr_as_json) {
- sgj_opaque_p jo2p;
-
- jo2p = sgj_new_unattached_object(jsp);
- sgj_get_designation_descriptor(jsp, jo2p, bp, i_len + 4);
- sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p);
- if (jsp->pr_out_hr)
- sgj_out_hr = true;
- else
- continue;
- }
assoc = ((bp[1] >> 4) & 0x3);
if (print_if_found && (! printed)) {
printed = true;
@@ -1146,210 +963,53 @@ filter_dev_ids(const char * print_if_found, int num_leading, uint8_t * buff,
return 0;
}
-/* VPD_EXT_INQ Extended Inquiry VPD */
+/* VPD_ATA_INFO 0x89 ['ai"] */
static void
-decode_x_inq_vpd(uint8_t * b, int len, int do_hex, bool do_long,
- bool protect)
-{
- int n;
-
- if (len < 7) {
- pr2serr("Extended INQUIRY data VPD page length too short=%d\n", len);
- return;
- }
- if (do_hex) {
- hex2stdout(b, len, (1 == do_hex) ? 0 : -1);
- return;
- }
- if (do_long) {
- n = (b[4] >> 6) & 0x3;
- printf(" ACTIVATE_MICROCODE=%d", n);
- if (1 == n)
- printf(" [before final WRITE BUFFER]\n");
- else if (2 == n)
- printf(" [after power on or hard reset]\n");
- else
- printf("\n");
- n = (b[4] >> 3) & 0x7;
- printf(" SPT=%d", n);
- if (protect) {
- switch (n)
- {
- case 0:
- printf(" [protection type 1 supported]\n");
- break;
- case 1:
- printf(" [protection types 1 and 2 supported]\n");
- break;
- case 2:
- printf(" [protection type 2 supported]\n");
- break;
- case 3:
- printf(" [protection types 1 and 3 supported]\n");
- break;
- case 4:
- printf(" [protection type 3 supported]\n");
- break;
- case 5:
- printf(" [protection types 2 and 3 supported]\n");
- break;
- case 6:
- printf(" [see Supported block lengths and protection types "
- "VPD page]\n");
- break;
- case 7:
- printf(" [protection types 1, 2 and 3 supported]\n");
- break;
- }
- } else
- printf("\n");
- printf(" GRD_CHK=%d\n", !!(b[4] & 0x4));
- printf(" APP_CHK=%d\n", !!(b[4] & 0x2));
- printf(" REF_CHK=%d\n", !!(b[4] & 0x1));
- printf(" UASK_SUP=%d\n", !!(b[5] & 0x20));
- printf(" GROUP_SUP=%d\n", !!(b[5] & 0x10));
- printf(" PRIOR_SUP=%d\n", !!(b[5] & 0x8));
- printf(" HEADSUP=%d\n", !!(b[5] & 0x4));
- printf(" ORDSUP=%d\n", !!(b[5] & 0x2));
- printf(" SIMPSUP=%d\n", !!(b[5] & 0x1));
- printf(" WU_SUP=%d\n", !!(b[6] & 0x8));
- printf(" CRD_SUP=%d\n", !!(b[6] & 0x4));
- printf(" NV_SUP=%d\n", !!(b[6] & 0x2));
- printf(" V_SUP=%d\n", !!(b[6] & 0x1));
- printf(" NO_PI_CHK=%d\n", !!(b[7] & 0x10)); /* spc5r02 */
- printf(" P_I_I_SUP=%d\n", !!(b[7] & 0x10));
- printf(" LUICLR=%d\n", !!(b[7] & 0x1));
- printf(" LU_COLL_TYPE=%d\n", (b[8] >> 5) & 0x7); /* spc5r09 */
- printf(" R_SUP=%d\n", !!(b[8] & 0x10));
- printf(" RTD_SUP=%d\n", !!(b[8] & 0x8)); /* spc5r11 */
- printf(" HSSRELEF=%d\n", !!(b[8] & 0x2)); /* spc5r02 */
- printf(" CBCS=%d\n", !!(b[8] & 0x1)); /* obsolete in spc5r01 */
- printf(" Multi I_T nexus microcode download=%d\n", b[9] & 0xf);
- printf(" Extended self-test completion minutes=%d\n",
- sg_get_unaligned_be16(b + 10));
- printf(" POA_SUP=%d\n", !!(b[12] & 0x80)); /* spc4r32 */
- printf(" HRA_SUP=%d\n", !!(b[12] & 0x40)); /* spc4r32 */
- printf(" VSA_SUP=%d\n", !!(b[12] & 0x20)); /* spc4r32 */
- printf(" DMS_VALID=%d\n", !!(b[12] & 0x10)); /* spc5r20 */
- printf(" Maximum supported sense data length=%d\n",
- b[13]); /* spc4r34 */
- printf(" IBS=%d\n", !!(b[14] & 0x80)); /* spc5r09 */
- printf(" IAS=%d\n", !!(b[14] & 0x40)); /* spc5r09 */
- printf(" SAC=%d\n", !!(b[14] & 0x4)); /* spc5r09 */
- printf(" NRD1=%d\n", !!(b[14] & 0x2)); /* spc5r09 */
- printf(" NRD0=%d\n", !!(b[14] & 0x1)); /* spc5r09 */
- printf(" Maximum inquiry change logs=%u\n",
- sg_get_unaligned_be16(b + 15)); /* spc5r17 */
- printf(" Maximum mode page change logs=%u\n",
- sg_get_unaligned_be16(b + 17)); /* spc5r17 */
- printf(" DM_MD_4=%d\n", !!(b[19] & 0x80)); /* spc5r20 */
- printf(" DM_MD_5=%d\n", !!(b[19] & 0x40)); /* spc5r20 */
- printf(" DM_MD_6=%d\n", !!(b[19] & 0x20)); /* spc5r20 */
- printf(" DM_MD_7=%d\n", !!(b[19] & 0x10)); /* spc5r20 */
- printf(" DM_MD_D=%d\n", !!(b[19] & 0x8)); /* spc5r20 */
- printf(" DM_MD_E=%d\n", !!(b[19] & 0x4)); /* spc5r20 */
- printf(" DM_MD_F=%d\n", !!(b[19] & 0x2)); /* spc5r20 */
- return;
- }
- printf(" ACTIVATE_MICROCODE=%d SPT=%d GRD_CHK=%d APP_CHK=%d "
- "REF_CHK=%d\n", ((b[4] >> 6) & 0x3), ((b[4] >> 3) & 0x7),
- !!(b[4] & 0x4), !!(b[4] & 0x2), !!(b[4] & 0x1));
- printf(" UASK_SUP=%d GROUP_SUP=%d PRIOR_SUP=%d HEADSUP=%d ORDSUP=%d "
- "SIMPSUP=%d\n", !!(b[5] & 0x20), !!(b[5] & 0x10), !!(b[5] & 0x8),
- !!(b[5] & 0x4), !!(b[5] & 0x2), !!(b[5] & 0x1));
- printf(" WU_SUP=%d [CRD_SUP=%d] NV_SUP=%d V_SUP=%d\n",
- !!(b[6] & 0x8), !!(b[6] & 0x4), !!(b[6] & 0x2), !!(b[6] & 0x1));
- printf(" NO_PI_CHK=%d P_I_I_SUP=%d LUICLR=%d\n", !!(b[7] & 0x20),
- !!(b[7] & 0x10), !!(b[7] & 0x1));
- /* RTD_SUP added in spc5r11, LU_COLL_TYPE added in spc5r09,
- * HSSRELEF added in spc5r02; CBCS obsolete in spc5r01 */
- printf(" LU_COLL_TYPE=%d R_SUP=%d RTD_SUP=%d HSSRELEF=%d [CBCS=%d]\n",
- (b[8] >> 5) & 0x7, !!(b[8] & 0x10), !!(b[8] & 0x8),
- !!(b[8] & 0x2), !!(b[8] & 0x1));
- printf(" Multi I_T nexus microcode download=%d\n", b[9] & 0xf);
- printf(" Extended self-test completion minutes=%d\n",
- sg_get_unaligned_be16(b + 10)); /* spc4r27 */
- printf(" POA_SUP=%d HRA_SUP=%d VSA_SUP=%d DMS_VALID=%d\n",
- !!(b[12] & 0x80), !!(b[12] & 0x40), !!(b[12] & 0x20),
- !!(b[12] & 0x10)); /* spc5r20 */
- printf(" Maximum supported sense data length=%d\n", b[13]); /* spc4r34 */
- printf(" IBS=%d IAS=%d SAC=%d NRD1=%d NRD0=%d\n", !!(b[14] & 0x80),
- !!(b[14] & 0x40), !!(b[14] & 0x4), !!(b[14] & 0x2),
- !!(b[14] & 0x1)); /* added in spc5r09 */
- printf(" Maximum inquiry change logs=%u\n",
- sg_get_unaligned_be16(b + 15)); /* spc5r17 */
- printf(" Maximum mode page change logs=%u\n",
- sg_get_unaligned_be16(b + 17)); /* spc5r17 */
- printf(" DM_MD_4=%d DM_MD_5=%d DM_MD_6=%d DM_MD_7=%d\n",
- !!(b[19] & 0x80), !!(b[19] & 0x40), !!(b[19] & 0x20),
- !!(b[19] & 0x10)); /* spc5r20 */
- printf(" DM_MD_D=%d DM_MD_E=%d DM_MD_F=%d\n",
- !!(b[19] & 0x8), !!(b[19] & 0x4), !!(b[19] & 0x2));
-}
-
-/* VPD_SOFTW_INF_ID */
-static void
-decode_softw_inf_id(uint8_t * buff, int len, struct opts_t * op,
- sgj_opaque_p jap)
+decode_ata_info_vpd(const uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jop)
{
+ bool do_long_nq = op->do_long && (! op->do_quiet);
+ int num, is_be, cc, n;
sgj_state * jsp = &op->json_st;
- sgj_opaque_p jop;
- uint64_t ieee_id;
-
- if (op->do_hex) {
- hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
- return;
- }
- len -= 4;
- buff += 4;
- for ( ; len > 5; len -= 6, buff += 6) {
- ieee_id = sg_get_unaligned_be48(buff + 0);
- sgj_pr_hr(jsp, " IEEE identifier: 0x%" PRIx64 "\n", ieee_id);
- if (jsp->pr_as_json) {
- jop = sgj_new_unattached_object(jsp);
- sgj_add_nv_ihex(jsp, jop, "ieee_identifier", ieee_id);
- sgj_add_nv_o(jsp, jap, NULL /* name */, jop);
- }
- }
-}
-
-/* VPD_ATA_INFO */
-static void
-decode_ata_info_vpd(uint8_t * buff, int len, int do_long, int do_hex)
-{
- char b[80];
- int num, is_be, cc;
const char * cp;
const char * ata_transp;
+ char b[144];
+ char d[80];
+ static const int blen = sizeof(b);
+ static const int dlen = sizeof(d);
+ static const char * sat_vip = "SAT Vendor identification";
+ static const char * sat_pip = "SAT Product identification";
+ static const char * sat_prlp = "SAT Product revision level";
if (len < 36) {
pr2serr("ATA information VPD page length too short=%d\n", len);
return;
}
- if (do_hex && (2 != do_hex)) {
- hex2stdout(buff, len, (1 == do_hex) ? 0 : -1);
+ if (op->do_hex && (2 != op->do_hex)) {
+ hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
return;
}
memcpy(b, buff + 8, 8);
b[8] = '\0';
- printf(" SAT Vendor identification: %s\n", b);
+ sgj_pr_hr(jsp, " %s: %s\n", sat_vip, b);
memcpy(b, buff + 16, 16);
b[16] = '\0';
- printf(" SAT Product identification: %s\n", b);
+ sgj_pr_hr(jsp, " %s: %s\n", sat_pip, b);
memcpy(b, buff + 32, 4);
b[4] = '\0';
- printf(" SAT Product revision level: %s\n", b);
+ sgj_pr_hr(jsp, " %s: %s\n", sat_prlp, b);
if (len < 56)
return;
ata_transp = (0x34 == buff[36]) ? "SATA" : "PATA";
- if (do_long) {
- printf(" Device signature [%s] (in hex):\n", ata_transp);
+ if (do_long_nq) {
+ sgj_pr_hr(jsp, " Device signature [%s] (in hex):\n", ata_transp);
hex2stdout(buff + 36, 20, 0);
} else
- printf(" Device signature indicates %s transport\n", ata_transp);
+ sgj_pr_hr(jsp, " Device signature indicates %s transport\n",
+ ata_transp);
cc = buff[56]; /* 0xec for IDENTIFY DEVICE and 0xa1 for IDENTIFY
* PACKET DEVICE (obsolete) */
- printf(" Command code: 0x%x\n", cc);
+ n = snprintf(b, blen, " Command code: 0x%x\n", cc);
if (len < 60)
return;
if (0xec == cc)
@@ -1360,62 +1020,47 @@ decode_ata_info_vpd(uint8_t * buff, int len, int do_long, int do_hex)
cp = NULL;
is_be = sg_is_big_endian();
if (cp) {
- printf(" ATA command IDENTIFY %sDEVICE response summary:\n", cp);
+ n += sg_scnpr(b + n, blen - n, " ATA command IDENTIFY %sDEVICE "
+ "response summary:\n", cp);
num = sg_ata_get_chars((const unsigned short *)(buff + 60), 27, 20,
- is_be, b);
- b[num] = '\0';
- printf(" model: %s\n", b);
+ is_be, d);
+ d[num] = '\0';
+ n += sg_scnpr(b + n, blen - n, " model: %s\n", d);
num = sg_ata_get_chars((const unsigned short *)(buff + 60), 10, 10,
- is_be, b);
- b[num] = '\0';
- printf(" serial number: %s\n", b);
+ is_be, d);
+ d[num] = '\0';
+ n += sg_scnpr(b + n, blen - n, " serial number: %s\n", d);
num = sg_ata_get_chars((const unsigned short *)(buff + 60), 23, 4,
- is_be, b);
- b[num] = '\0';
- printf(" firmware revision: %s\n", b);
- if (do_long)
- printf(" ATA command IDENTIFY %sDEVICE response in hex:\n", cp);
- } else if (do_long)
- printf(" ATA command 0x%x got following response:\n",
- (unsigned int)cc);
+ is_be, d);
+ d[num] = '\0';
+ n += sg_scnpr(b + n, blen - n, " firmware revision: %s\n", d);
+ sgj_pr_hr(jsp, "%s", b);
+ if (do_long_nq)
+ sgj_pr_hr(jsp, " ATA command IDENTIFY %sDEVICE response in "
+ "hex:\n", cp);
+ } else if (do_long_nq)
+ sgj_pr_hr(jsp, " ATA command 0x%x got following response:\n",
+ (unsigned int)cc);
+ if (jsp->pr_as_json) {
+ sgj_convert_to_snake_name(sat_vip, d, dlen);
+ sgj_add_nv_s_len(jsp, jop, d, (const char *)(buff + 8), 8);
+ sgj_convert_to_snake_name(sat_pip, d, dlen);
+ sgj_add_nv_s_len(jsp, jop, d, (const char *)(buff + 16), 16);
+ sgj_convert_to_snake_name(sat_prlp, d, dlen);
+ sgj_add_nv_s_len(jsp, jop, d, (const char *)(buff + 32), 4);
+ sgj_add_nv_hex_bytes(jsp, jop, "ata_device_signature", buff + 36, 20);
+ sgj_add_nv_ihex(jsp, jop, "command_code", buff[56]);
+ sgj_add_nv_s(jsp, jop, "ata_identify_device_data_example",
+ "sg_vpd -p ai -HHH /dev/sdc | hdparm --Istdin");
+ }
if (len < 572)
return;
- if (2 == do_hex)
+ if (2 == op->do_hex)
hex2stdout((buff + 60), 512, 0);
- else if (do_long)
+ else if (do_long_nq)
dWordHex((const unsigned short *)(buff + 60), 256, 0, is_be);
}
-
-/* VPD_POWER_CONDITION 0x8a */
-static void
-decode_power_condition(uint8_t * buff, int len, int do_hex)
-{
- if (len < 18) {
- pr2serr("Power condition VPD page length too short=%d\n", len);
- return;
- }
- if (do_hex) {
- hex2stdout(buff, len, (1 == do_hex) ? 0 : -1);
- return;
- }
- printf(" Standby_y=%d Standby_z=%d Idle_c=%d Idle_b=%d Idle_a=%d\n",
- !!(buff[4] & 0x2), !!(buff[4] & 0x1),
- !!(buff[5] & 0x4), !!(buff[5] & 0x2), !!(buff[5] & 0x1));
- printf(" Stopped condition recovery time (ms) %d\n",
- sg_get_unaligned_be16(buff + 6));
- printf(" Standby_z condition recovery time (ms) %d\n",
- sg_get_unaligned_be16(buff + 8));
- printf(" Standby_y condition recovery time (ms) %d\n",
- sg_get_unaligned_be16(buff + 10));
- printf(" Idle_a condition recovery time (ms) %d\n",
- sg_get_unaligned_be16(buff + 12));
- printf(" Idle_b condition recovery time (ms) %d\n",
- sg_get_unaligned_be16(buff + 14));
- printf(" Idle_c condition recovery time (ms) %d\n",
- sg_get_unaligned_be16(buff + 16));
-}
-
static const char * constituent_type_arr[] = {
"Reserved",
"Virtual tape library",
@@ -3076,14 +2721,14 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
}
break;
- case VPD_SUPPORTED_VPDS: /* 0x0 */
- np = "Supported VPD pages VPD page:";
+ case VPD_SUPPORTED_VPDS: /* 0x0 ["sv"] */
+ np = "Supported VPD pages";
if (allow_name)
- sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
if (! allow_name && allow_if_found)
- sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
if (op->do_raw)
dStrRaw(rp, len);
else if (op->do_hex)
@@ -3096,12 +2741,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (num > (len - 4))
num = (len - 4);
if (as_json) {
- jo2p = sgj_new_snake_named_object(jsp, jop, np);
- sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_qualifier",
- pqual, NULL, pqual_str(pqual));
- sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_device_type",
- pdt, NULL, pdt_str);
- sgj_add_nv_ihex(jsp, jo2p, "page_code", pn);
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
jap = sgj_new_named_array(jsp, jo2p,
"supported_vpd_page_list");
}
@@ -3147,14 +2787,14 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
}
break;
- case VPD_UNIT_SERIAL_NUM: /* 0x80 */
- np = "Unit serial number VPD page:";
+ case VPD_UNIT_SERIAL_NUM: /* 0x80 ["sn"] */
+ np = "Unit serial number";
if (allow_name && not_json)
- sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s VPD page:\n", pre, np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
if (! allow_name && allow_if_found)
- sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
if (op->do_raw)
dStrRaw(rp, len);
else if (op->do_hex)
@@ -3168,26 +2808,21 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (len >= (int)sizeof(obuff))
len = sizeof(obuff) - 1;
memcpy(obuff, rp + 4, len);
- jo2p = sgj_new_snake_named_object(jsp, jop, np);
- sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_qualifier",
- pqual, NULL, pqual_str(pqual));
- sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_device_type",
- pdt, NULL, pdt_str);
- sgj_add_nv_ihex(jsp, jo2p, "page_code", pn);
- sgj_pr_hr_js_vs(jsp, jo2p, 2, "unit_serial_number",
- SGJ_SEP_COLON_1_SPACE, obuff);
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ sgj_pr_hr_js_vs(jsp, jo2p, 2, np, SGJ_SEP_COLON_1_SPACE,
+ obuff);
}
return 0;
}
break;
- case VPD_DEVICE_ID: /* 0x83 */
- np = "Device Identification VPD page:";
+ case VPD_DEVICE_ID: /* 0x83 ["di, di_asis, di_lu, di_port, di_target"] */
+ np = "Device Identification";
if (allow_name)
- sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
if (! allow_name && allow_if_found)
- sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
if (op->do_raw)
dStrRaw(rp, len);
else if (op->do_hex)
@@ -3197,12 +2832,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
"%s]\n", pqual, pdt_str);
if (as_json) {
- jo2p = sgj_new_snake_named_object(jsp, jop, np);
- sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_qualifier",
- pqual, NULL, pqual_str(pqual));
- sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_device_type",
- pdt, NULL, pdt_str);
- sgj_add_nv_ihex(jsp, jo2p, "page_code", pn);
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
jap = sgj_new_named_array(jsp, jo2p,
"designation_descriptor_list");
}
@@ -3211,14 +2841,14 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
}
break;
- case VPD_SOFTW_INF_ID: /* 0x84 */
- np = "Software interface identification VPD page:";
+ case VPD_SOFTW_INF_ID: /* 0x84 ["sii"] */
+ np = "Software interface identification";
if (allow_name)
- sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
if (! allow_name && allow_if_found)
- sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
if (op->do_raw)
dStrRaw(rp, len);
else {
@@ -3226,12 +2856,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
"%s]\n", pqual, pdt_str);
if (as_json) {
- jo2p = sgj_new_snake_named_object(jsp, jop, np);
- sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_qualifier",
- pqual, NULL, pqual_str(pqual));
- sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_device_type",
- pdt, NULL, pdt_str);
- sgj_add_nv_ihex(jsp, jo2p, "page_code", pn);
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
jap = sgj_new_named_array(jsp, jo2p,
"software_interface_identifier_list");
}
@@ -3240,24 +2865,19 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
}
break;
- case VPD_MAN_NET_ADDR: /* 0x85 */
- np= "Management network addresses VPD page:";
+ case VPD_MAN_NET_ADDR: /* 0x85 ["mna"] */
+ np= "Management network addresses";
if (allow_name)
- sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
if (! allow_name && allow_if_found)
- sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
if (op->do_raw)
dStrRaw(rp, len);
else {
if (as_json) {
- jo2p = sgj_new_snake_named_object(jsp, jop, np);
- sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_qualifier",
- pqual, NULL, pqual_str(pqual));
- sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_device_type",
- pdt, NULL, pdt_str);
- sgj_add_nv_ihex(jsp, jo2p, "page_code", pn);
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
jap = sgj_new_named_array(jsp, jo2p,
"network_services_descriptor_list");
}
@@ -3266,14 +2886,14 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
}
break;
- case VPD_EXT_INQ: /* 0x86 */
- np = "extended INQUIRY data VPD page:";
+ case VPD_EXT_INQ: /* 0x86 ["ei"] */
+ np = "extended INQUIRY data";
if (allow_name)
- printf("%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
if (! allow_name && allow_if_found)
- printf("%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
if (op->do_raw)
dStrRaw(rp, len);
else {
@@ -3290,40 +2910,48 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
protect = !!(sir.byte_5 & 0x1); /* SPC-3 and later */
}
if (vb || long_notquiet)
- printf(" [PQual=%d Peripheral device type: %s]\n",
- pqual, pdt_str);
- decode_x_inq_vpd(rp, len, op->do_hex, long_notquiet, protect);
+ sgj_pr_hr(jsp," [PQual=%d Peripheral device type: "
+ "%s]\n", pqual, pdt_str);
+ if (as_json)
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ decode_x_inq_vpd(rp, len, protect, op, jo2p);
}
return 0;
}
break;
case VPD_MODE_PG_POLICY: /* 0x87 */
- np = "Mode page policy VPD page:";
+ np = "Mode page policy";
if (allow_name)
- printf("%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
if (! allow_name && allow_if_found)
- printf("%s%s\n", (prefix ? prefix : ""), np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", (prefix ? prefix : ""), np,
+ vpd_p_s);
if (op->do_raw)
dStrRaw(rp, len);
else {
if (vb || long_notquiet)
- printf(" [PQual=%d Peripheral device type: %s]\n",
- pqual, pdt_str);
- decode_mode_policy_vpd(rp, len, op->do_hex);
+ sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
+ "%s]\n", pqual, pdt_str);
+ if (as_json) {
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ jap = sgj_new_named_array(jsp, jo2p,
+ "mode_page_policy_descriptor_list");
+ }
+ decode_mode_policy_vpd(rp, len, op, jap);
}
return 0;
}
break;
- case VPD_SCSI_PORTS: /* 0x88 */
- np = "SCSI Ports VPD page:";
+ case VPD_SCSI_PORTS: /* 0x88 ["sp"] */
+ np = "SCSI Ports";
if (allow_name)
- sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
if (! allow_name && allow_if_found)
- sgj_pr_hr(jsp, "%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
if (op->do_raw)
dStrRaw(rp, len);
else {
@@ -3331,29 +2959,25 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
"%s]\n", pqual, pdt_str);
if (as_json) {
- jo2p = sgj_new_snake_named_object(jsp, jop, np);
- sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_qualifier",
- pqual, NULL, pqual_str(pqual));
- sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_device_type",
- pdt, NULL, pdt_str);
- sgj_add_nv_ihex(jsp, jo2p, "page_code", pn);
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
jap = sgj_new_named_array(jsp, jo2p,
- "scsi_port_descriptor_list");
+ "scsi_ports_descriptor_list");
}
decode_scsi_ports_vpd(rp, len, op, jap);
}
return 0;
}
break;
- case VPD_ATA_INFO: /* 0x89 */
- np = "ATA information VPD page:";
+ case VPD_ATA_INFO: /* 0x89 ['ai"] */
+ np = "ATA information";
if (allow_name)
- printf("%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", pre, np, vpd_p_s);
alloc_len = op->maxlen ? op->maxlen : VPD_ATA_INFO_LEN;
res = vpd_fetch_page(sg_fd, rp, pn, alloc_len, qt, vb, &len);
if (0 == res) {
if (! allow_name && allow_if_found)
- printf("%s%s\n", (prefix ? prefix : ""), np);
+ sgj_pr_hr(jsp, "%s%s %s:\n", (prefix ? prefix : ""), np,
+ vpd_p_s);
if ((2 == op->do_raw) || (3 == op->do_hex)) { /* for hdparm */
if (len < (60 + 512))
pr2serr("ATA_INFO VPD page len (%d) less than expected "
@@ -3366,28 +2990,30 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
dStrRaw(rp, len);
else {
if (vb || long_notquiet)
- printf(" [PQual=%d Peripheral device type: %s]\n",
- pqual, pdt_str);
- decode_ata_info_vpd(rp, len, long_notquiet, op->do_hex);
+ sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
+ "%s]\n", pqual, pdt_str);
+ if (as_json)
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ decode_ata_info_vpd(rp, len, op, jo2p);
}
return 0;
}
break;
- case VPD_POWER_CONDITION: /* 0x8a */
+ case VPD_POWER_CONDITION: /* 0x8a ["pc"\ */
np = "Power condition VPD page:";
if (allow_name)
- printf("%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s\n", pre, np);
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
if (! allow_name && allow_if_found)
- printf("%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s\n", pre, np);
if (op->do_raw)
dStrRaw(rp, len);
else {
if (vb || long_notquiet)
- printf(" [PQual=%d Peripheral device type: %s]\n",
- pqual, pdt_str);
- decode_power_condition(rp, len, op->do_hex);
+ sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
+ "%s]\n", pqual, pdt_str);
+ decode_power_condition(rp, len, op, jop);
}
return 0;
}
@@ -3996,6 +3622,7 @@ main(int argc, char * argv[])
struct opts_t opts = {0};
struct opts_t * op = &opts;
+ op->invoker = SG_VPD_INV_SG_VPD;
dup_sanity_chk((int)sizeof(opts), (int)sizeof(*vnp));
op->vend_prod_num = -1;
while (1) {
@@ -4189,8 +3816,8 @@ main(int argc, char * argv[])
return 0;
}
- as_json = op->json_st.pr_as_json;
jsp = &op->json_st;
+ as_json = jsp->pr_as_json;
if (as_json)
jop = sgj_start(MY_NAME, version_str, argc, argv, jsp);
diff --git a/src/sg_vpd.h b/src/sg_vpd.h
deleted file mode 100644
index f01ef122..00000000
--- a/src/sg_vpd.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef SG_VPD_H
-#define SG_VPD_H
-
-/*
- * Copyright (c) 2022 Douglas Gilbert.
- * All rights reserved.
- * Use of this source code is governed by a BSD-style
- * license that can be found in the BSD_LICENSE file.
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "sg_lib.h"
-#include "sg_pr2serr.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* These two structures are duplicates of those of the same name in
- * sg_vpd_vendor.c . <<< Take care that both are the same. >>> */
-struct opts_t {
- bool do_all;
- bool do_enum;
- bool do_force;
- bool do_long;
- bool do_quiet;
- bool page_given;
- bool verbose_given;
- bool version_given;
- int do_hex;
- int do_ident;
- int do_raw;
- int examine;
- int maxlen;
- int vend_prod_num;
- int verbose;
- int vpd_pn;
- const char * device_name;
- const char * page_str;
- const char * inhex_fn;
- const char * vend_prod;
- sgj_state json_st;
-};
-
-struct svpd_values_name_t {
- int value; /* VPD page number */
- int subvalue; /* to differentiate if value+pdt are not unique */
- int pdt; /* peripheral device type id, -1 is the default */
- /* (all or not applicable) value */
- const char * acron;
- const char * name;
-};
-
-void svpd_enumerate_vendor(int vend_prod_num);
-int svpd_count_vendor_vpds(int vpd_pn, int vend_prod_num);
-int svpd_decode_vendor(int sg_fd, struct opts_t * op, int off);
-const struct svpd_values_name_t * svpd_find_vendor_by_acron(const char * ap);
-int svpd_find_vp_num_by_acron(const char * vp_ap);
-const struct svpd_values_name_t * svpd_find_vendor_by_num(int page_num,
- int vend_prod_num);
-int vpd_fetch_page(int sg_fd, uint8_t * rp, int page, int mxlen,
- bool qt, int vb, int * rlenp);
-void dup_sanity_chk(int sz_opts_t, int sz_values_name_t);
-
-extern uint8_t * rsp_buff;
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* end of SG_VPD_H */
diff --git a/src/sg_vpd_common.c b/src/sg_vpd_common.c
new file mode 100644
index 00000000..49d18670
--- /dev/null
+++ b/src/sg_vpd_common.c
@@ -0,0 +1,558 @@
+/*
+ * Copyright (c) 2006-2022 Douglas Gilbert.
+ * All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the BSD_LICENSE file.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#include <ctype.h>
+#include <getopt.h>
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "sg_lib.h"
+#include "sg_cmds_basic.h"
+#include "sg_unaligned.h"
+#include "sg_pr2serr.h"
+
+#include "sg_vpd_common.h"
+
+/* This file holds common code for sg_inq and sg_vpd as both those utilities
+ * decode SCSI VPD pages. */
+
+sgj_opaque_p
+sg_vpd_js_hdr(sgj_state * jsp, sgj_opaque_p jop, const char * name,
+ const uint8_t * vpd_hdrp)
+{
+ int pdt = vpd_hdrp[0] & PDT_MASK;
+ int pqual = (vpd_hdrp[0] & 0xe0) >> 5;
+ int pn = vpd_hdrp[1];
+ const char * pdt_str;
+ sgj_opaque_p jo2p = sgj_new_snake_named_object(jsp, jop, name);
+ char d[64];
+
+ pdt_str = sg_get_pdt_str(pdt, sizeof(d), d);
+ sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_qualifier",
+ pqual, NULL, pqual_str(pqual));
+ sgj_add_nv_ihexstr(jsp, jo2p, "peripheral_device_type",
+ pdt, NULL, pdt_str);
+ sgj_add_nv_ihex(jsp, jo2p, "page_code", pn);
+ return jo2p;
+}
+
+const char *
+pqual_str(int pqual)
+{
+ switch (pqual) {
+ case 0:
+ return "LU accessible";
+ case 1:
+ return "LU temporarily unavailable";
+ case 3:
+ return "LU not accessible via this port";
+ default:
+ return "value reserved by T10";
+ }
+}
+
+static const char * network_service_type_arr[] =
+{
+ "unspecified",
+ "storage configuration service",
+ "diagnostics",
+ "status",
+ "logging",
+ "code download",
+ "copy service",
+ "administrative configuration service",
+ "reserved[0x8]", "reserved[0x9]",
+ "reserved[0xa]", "reserved[0xb]", "reserved[0xc]", "reserved[0xd]",
+ "reserved[0xe]", "reserved[0xf]", "reserved[0x10]", "reserved[0x11]",
+ "reserved[0x12]", "reserved[0x13]", "reserved[0x14]", "reserved[0x15]",
+ "reserved[0x16]", "reserved[0x17]", "reserved[0x18]", "reserved[0x19]",
+ "reserved[0x1a]", "reserved[0x1b]", "reserved[0x1c]", "reserved[0x1d]",
+ "reserved[0x1e]", "reserved[0x1f]",
+};
+
+/* VPD_MAN_NET_ADDR 0x85 ["mna"] */
+void
+decode_net_man_vpd(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap)
+{
+ int k, bump, na_len, assoc, nst;
+ sgj_state * jsp = &op->json_st;
+ sgj_opaque_p jo2p;
+ uint8_t * bp;
+ const char * assoc_str;
+ const char * nst_str;
+
+ if ((1 == op->do_hex) || (op->do_hex > 2)) {
+ hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
+ return;
+ }
+ if (len < 4) {
+ pr2serr("Management network addresses VPD page length too short=%d\n",
+ len);
+ return;
+ }
+ len -= 4;
+ bp = buff + 4;
+ for (k = 0; k < len; k += bump, bp += bump) {
+ assoc = (bp[0] >> 5) & 0x3;
+ assoc_str = sg_get_desig_assoc_str(assoc);
+ nst = bp[0] & 0x1f;
+ nst_str = network_service_type_arr[nst];
+ sgj_pr_hr(jsp, " %s, Service type: %s\n", assoc_str, nst_str);
+ na_len = sg_get_unaligned_be16(bp + 2);
+ if (jsp->pr_as_json) {
+ jo2p = sgj_new_unattached_object(jsp);
+ sgj_add_nv_ihexstr(jsp, jo2p, "association", assoc, NULL,
+ assoc_str);
+ sgj_add_nv_ihexstr(jsp, jo2p, "service_type", nst, NULL,
+ nst_str);
+ sgj_add_nv_s_len(jsp, jo2p, "network_address",
+ (const char *)(bp + 4), na_len);
+ sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p);
+ }
+ if (na_len > 0) {
+ if (op->do_hex > 1) {
+ sgj_pr_hr(jsp, " Network address:\n");
+ hex2stdout((bp + 4), na_len, 0);
+ } else
+ sgj_pr_hr(jsp, " %s\n", bp + 4);
+ }
+ bump = 4 + na_len;
+ if ((k + bump) > len) {
+ pr2serr("Management network addresses VPD page, short "
+ "descriptor length=%d, left=%d\n", bump, (len - k));
+ return;
+ }
+ }
+}
+
+/* VPD_EXT_INQ Extended Inquiry VPD ["ei"] */
+void
+decode_x_inq_vpd(uint8_t * b, int len, bool protect, struct opts_t * op,
+ sgj_opaque_p jop)
+{
+ bool do_long_nq = op->do_long && (! op->do_quiet);
+ int n;
+ sgj_state * jsp = &op->json_st;
+ sgj_opaque_p jo2p;
+ const char * cp;
+ const char * np;
+ const char * nex_p;
+ char d[128];
+ static const int dlen = sizeof(d);
+
+ if (len < 7) {
+ pr2serr("Extended INQUIRY data VPD page length too short=%d\n", len);
+ return;
+ }
+ if (op->do_hex) {
+ hex2stdout(b, len, (1 == op->do_hex) ? 0 : -1);
+ return;
+ }
+ if (do_long_nq || jsp->pr_as_json) {
+ n = (b[4] >> 6) & 0x3;
+ if (1 == n)
+ cp = "before final WRITE BUFFER";
+ else if (2 == n)
+ cp = "after power on or hard reset";
+ else {
+ cp = "none";
+ d[0] = '\0';
+ }
+ if (cp[0])
+ snprintf(d, dlen, " [%s]", cp);
+ sgj_pr_hr(jsp, " ACTIVATE_MICROCODE=%d%s\n", n, d);
+ sgj_add_nv_ihexstr(jsp, jop, "activate_microcode", n, NULL, cp);
+ n = (b[4] >> 3) & 0x7;
+ if (protect) {
+ switch (n)
+ {
+ case 0:
+ cp = "protection type 1 supported";
+ break;
+ case 1:
+ cp = "protection types 1 and 2 supported";
+ break;
+ case 2:
+ cp = "protection type 2 supported";
+ break;
+ case 3:
+ cp = "protection types 1 and 3 supported";
+ break;
+ case 4:
+ cp = "protection type 3 supported";
+ break;
+ case 5:
+ cp = "protection types 2 and 3 supported";
+ break;
+ case 6:
+ cp = "see Supported block lengths and protection types "
+ "VPD page";
+ break;
+ case 7:
+ cp = "protection types 1, 2 and 3 supported";
+ break;
+ }
+ } else {
+ cp = "none";
+ d[0] = '\0';
+ }
+ if (cp[0])
+ snprintf(d, dlen, " [%s]", cp);
+ sgj_pr_hr(jsp, " SPT=%d%s\n", n, d);
+ sgj_add_nv_ihexstr_nex(jsp, jop, "spt", n, false, NULL,
+ cp, "Supported Protection Type");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "GRD_CHK", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[4] & 0x4), "guard check");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "APP_CHK", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[4] & 0x2), "application tag check");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "REF_CHK", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[4] & 0x1), "reference tag check");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "UASK_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[5] & 0x20), "Unit Attention condition Sense "
+ "Key specific data Supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "GROUP_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[5] & 0x10), "grouping function supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "PRIOR_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[5] & 0x8), "priority supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "HEADSUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[5] & 0x4), "head of queue supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "ORDSUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[5] & 0x2), "ordered (task attribute) "
+ "supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "SIMPSUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[5] & 0x1), "simple (task attribute) "
+ "supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "WU_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[6] & 0x8), "Write uncorrectable supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "CRD_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[6] & 0x4), "Correction disable supported "
+ "(obsolete SPC-5)");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "NV_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[6] & 0x2), "Nonvolatile cache supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "V_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[6] & 0x1), "Volatile cache supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "NO_PI_CHK", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[7] & 0x20), "No protection information "
+ "checking"); /* spc5r02 */
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "P_I_I_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[7] & 0x10), "Protection information "
+ "interval supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "LUICLR", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[7] & 0x1), "Logical unit I_T nexus clear");
+ np = "LU_COLL_TYPE";
+ n = (b[8] >> 5) & 0x7;
+ nex_p = "Logical unit collection type";
+ if (jsp && (jsp->pr_string)) {
+ switch (n) {
+ case 0:
+ cp = "not reported";
+ break;
+ case 1:
+ cp = "Conglomerate";
+ break;
+ case 2:
+ cp = "Logical unit group";
+ break;
+ default:
+ cp = "reserved";
+ break;
+ }
+ jo2p = sgj_pr_hr_js_subo(jsp, jop, 2, np, SGJ_SEP_EQUAL_NO_SPACE,
+ n);
+ sgj_add_nv_s(jsp, jo2p, "meaning", cp);
+ if (jsp->pr_name_ex)
+ sgj_add_nv_s(jsp, jo2p, "abbreviated_name_expansion", nex_p);
+ } else
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, np, SGJ_SEP_EQUAL_NO_SPACE, n,
+ nex_p);
+
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "R_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[8] & 0x10), "Referrals supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "RTD_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[8] & 0x8), "Revert to defaults supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "HSSRELEF", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[8] & 0x2),
+ "History snapshots release effects");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "CBCS", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[8] & 0x1), "Capability-based command "
+ "security (obsolete SPC-5)");
+ sgj_pr_hr_js_vi(jsp, jop, 2, "Multi I_T nexus microcode download",
+ SGJ_SEP_EQUAL_NO_SPACE, b[9] & 0xf);
+ sgj_pr_hr_js_vi(jsp, jop, 2, "Extended self-test completion minutes",
+ SGJ_SEP_EQUAL_NO_SPACE,
+ sg_get_unaligned_be16(b + 10));
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "POA_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[12] & 0x80),
+ "Power on activation supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "HRA_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[12] & 0x40),
+ "Hard reset activation supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "VSA_SUP", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[12] & 0x20),
+ "Vendor specific activation supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "DMS_VALID", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[12] & 0x10),
+ "Download microcode support byte valid");
+ sgj_pr_hr_js_vi(jsp, jop, 2, "Maximum supported sense data length",
+ SGJ_SEP_EQUAL_NO_SPACE, b[13]);
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "IBS", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[14] & 0x80), "Implicit bind supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "IAS", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[14] & 0x40),
+ "Implicit affiliation supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "SAC", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[14] & 0x4),
+ "Set affiliation command supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "NRD1", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[14] & 0x2),
+ "No redirect one supported (BIND)");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "NRD0", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[14] & 0x1),
+ "No redirect zero supported (BIND)");
+ sgj_pr_hr_js_vi(jsp, jop, 2, "Maximum inquiry change logs",
+ SGJ_SEP_EQUAL_NO_SPACE,
+ sg_get_unaligned_be16(b + 15));
+ sgj_pr_hr_js_vi(jsp, jop, 2, "Maximum mode page change logs",
+ SGJ_SEP_EQUAL_NO_SPACE,
+ sg_get_unaligned_be16(b + 17));
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "DM_MD_4", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[19] & 0x80),
+ "Download microcode mode 4 supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "DM_MD_5", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[19] & 0x40),
+ "Download microcode mode 5 supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "DM_MD_6", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[19] & 0x20),
+ "Download microcode mode 6 supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "DM_MD_7", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[19] & 0x10),
+ "Download microcode mode 7 supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "DM_MD_D", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[19] & 0x8),
+ "Download microcode mode 0xd supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "DM_MD_E", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[19] & 0x4),
+ "Download microcode mode 0xe supported");
+ sgj_pr_hr_js_vi_nex(jsp, jop, 2, "DM_MD_F", SGJ_SEP_EQUAL_NO_SPACE,
+ !!(b[19] & 0x2),
+ "Download microcode mode 0xf supported");
+ if (do_long_nq || (! jsp->pr_out_hr))
+ return;
+ }
+ sgj_pr_hr(jsp, " ACTIVATE_MICROCODE=%d SPT=%d GRD_CHK=%d APP_CHK=%d "
+ "REF_CHK=%d\n", ((b[4] >> 6) & 0x3), ((b[4] >> 3) & 0x7),
+ !!(b[4] & 0x4), !!(b[4] & 0x2), !!(b[4] & 0x1));
+ sgj_pr_hr(jsp, " UASK_SUP=%d GROUP_SUP=%d PRIOR_SUP=%d HEADSUP=%d "
+ "ORDSUP=%d SIMPSUP=%d\n", !!(b[5] & 0x20), !!(b[5] & 0x10),
+ !!(b[5] & 0x8), !!(b[5] & 0x4), !!(b[5] & 0x2), !!(b[5] & 0x1));
+ sgj_pr_hr(jsp, " WU_SUP=%d [CRD_SUP=%d] NV_SUP=%d V_SUP=%d\n",
+ !!(b[6] & 0x8), !!(b[6] & 0x4), !!(b[6] & 0x2), !!(b[6] & 0x1));
+ sgj_pr_hr(jsp, " NO_PI_CHK=%d P_I_I_SUP=%d LUICLR=%d\n", !!(b[7] & 0x20),
+ !!(b[7] & 0x10), !!(b[7] & 0x1));
+ /* RTD_SUP added in spc5r11, LU_COLL_TYPE added in spc5r09,
+ * HSSRELEF added in spc5r02; CBCS obsolete in spc5r01 */
+ sgj_pr_hr(jsp, " LU_COLL_TYPE=%d R_SUP=%d RTD_SUP=%d HSSRELEF=%d "
+ "[CBCS=%d]\n", (b[8] >> 5) & 0x7, !!(b[8] & 0x10),
+ !!(b[8] & 0x8), !!(b[8] & 0x2), !!(b[8] & 0x1));
+ sgj_pr_hr(jsp, " Multi I_T nexus microcode download=%d\n", b[9] & 0xf);
+ sgj_pr_hr(jsp, " Extended self-test completion minutes=%d\n",
+ sg_get_unaligned_be16(b + 10)); /* spc4r27 */
+ sgj_pr_hr(jsp, " POA_SUP=%d HRA_SUP=%d VSA_SUP=%d DMS_VALID=%d\n",
+ !!(b[12] & 0x80), !!(b[12] & 0x40), !!(b[12] & 0x20),
+ !!(b[12] & 0x10)); /* spc5r20 */
+ sgj_pr_hr(jsp, " Maximum supported sense data length=%d\n",
+ b[13]); /* spc4r34 */
+ sgj_pr_hr(jsp, " IBS=%d IAS=%d SAC=%d NRD1=%d NRD0=%d\n",
+ !!(b[14] & 0x80), !!(b[14] & 0x40), !!(b[14] & 0x4),
+ !!(b[14] & 0x2), !!(b[14] & 0x1)); /* added in spc5r09 */
+ sgj_pr_hr(jsp, " Maximum inquiry change logs=%u\n",
+ sg_get_unaligned_be16(b + 15)); /* spc5r17 */
+ sgj_pr_hr(jsp, " Maximum mode page change logs=%u\n",
+ sg_get_unaligned_be16(b + 17)); /* spc5r17 */
+ sgj_pr_hr(jsp, " DM_MD_4=%d DM_MD_5=%d DM_MD_6=%d DM_MD_7=%d\n",
+ !!(b[19] & 0x80), !!(b[19] & 0x40), !!(b[19] & 0x20),
+ !!(b[19] & 0x10)); /* spc5r20 */
+ sgj_pr_hr(jsp, " DM_MD_D=%d DM_MD_E=%d DM_MD_F=%d\n",
+ !!(b[19] & 0x8), !!(b[19] & 0x4), !!(b[19] & 0x2));
+}
+
+/* VPD_SOFTW_INF_ID 0x84 */
+void
+decode_softw_inf_id(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap)
+{
+ sgj_state * jsp = &op->json_st;
+ sgj_opaque_p jop;
+ uint64_t ieee_id;
+
+ if (op->do_hex) {
+ hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
+ return;
+ }
+ len -= 4;
+ buff += 4;
+ for ( ; len > 5; len -= 6, buff += 6) {
+ ieee_id = sg_get_unaligned_be48(buff + 0);
+ sgj_pr_hr(jsp, " IEEE identifier: 0x%" PRIx64 "\n", ieee_id);
+ if (jsp->pr_as_json) {
+ jop = sgj_new_unattached_object(jsp);
+ sgj_add_nv_ihex(jsp, jop, "ieee_identifier", ieee_id);
+ sgj_add_nv_o(jsp, jap, NULL /* name */, jop);
+ }
+ }
+}
+
+static const char * mode_page_policy_arr[] =
+{
+ "shared",
+ "per target port",
+ "per initiator port",
+ "per I_T nexus",
+};
+
+/* VPD_MODE_PG_POLICY 0x87 ["mpp"] */
+void
+decode_mode_policy_vpd(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap)
+{
+ int k, n, bump, ppc, pspc;
+ sgj_state * jsp = &op->json_st;
+ sgj_opaque_p jo2p;
+ uint8_t * bp;
+ char b[128];
+ static const int blen = sizeof(b);
+
+ if ((1 == op->do_hex) || (op->do_hex > 2)) {
+ hex2stdout(buff, len, (1 == op->do_hex) ? 1 : -1);
+ return;
+ }
+ if (len < 4) {
+ pr2serr("Mode page policy VPD page length too short=%d\n", len);
+ return;
+ }
+ len -= 4;
+ bp = buff + 4;
+ for (k = 0; k < len; k += bump, bp += bump) {
+ bump = 4;
+ if ((k + bump) > len) {
+ pr2serr("Mode page policy VPD page, short "
+ "descriptor length=%d, left=%d\n", bump, (len - k));
+ return;
+ }
+ if (op->do_hex > 1)
+ hex2stdout(bp, 4, 1);
+ else {
+ n = 0;
+ ppc = (bp[0] & 0x3f);
+ pspc = bp[1];
+ snprintf(b + n, blen - n, " Policy page code: 0x%x", ppc);
+ if (pspc)
+ n += snprintf(b + n, blen - n, ", subpage code: 0x%x", pspc);
+ sgj_pr_hr(jsp, "%s\n", b);
+ if ((0 == k) && (0x3f == (0x3f & bp[0])) && (0xff == bp[1]))
+ sgj_pr_hr(jsp, " therefore the policy applies to all modes "
+ "pages and subpages\n");
+ sgj_pr_hr(jsp, " MLUS=%d, Policy: %s\n", !!(bp[2] & 0x80),
+ mode_page_policy_arr[bp[2] & 0x3]);
+ if (jsp->pr_as_json) {
+ jo2p = sgj_new_unattached_object(jsp);
+ sgj_add_nv_ihex(jsp, jo2p, "policy_page_code", ppc);
+ sgj_add_nv_ihex(jsp, jo2p, "policy_subpage_code", pspc);
+ sgj_add_nv_ihex_nex(jsp, jo2p, "mlus", !!(bp[2] & 0x80), false,
+ "Multiple logical units share");
+ sgj_add_nv_ihexstr(jsp, jo2p, "mode_page_policy", bp[2] & 0x3,
+ NULL, mode_page_policy_arr[bp[2] & 0x3]);
+ sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p);
+ }
+ }
+ }
+}
+
+/* VPD_POWER_CONDITION 0x8a ["pc"] */
+void
+decode_power_condition(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jop)
+{
+ sgj_state * jsp = &op->json_st;
+
+ if (len < 18) {
+ pr2serr("Power condition VPD page length too short=%d\n", len);
+ return;
+ }
+ if (op->do_hex) {
+ hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
+ return;
+ }
+ sgj_pr_hr(jsp, " Standby_y=%d Standby_z=%d Idle_c=%d Idle_b=%d "
+ "Idle_a=%d\n", !!(buff[4] & 0x2), !!(buff[4] & 0x1),
+ !!(buff[5] & 0x4), !!(buff[5] & 0x2), !!(buff[5] & 0x1));
+ if (jsp->pr_as_json) {
+ sgj_add_nv_ihex(jsp, jop, "standby_y", !!(buff[4] & 0x2));
+ sgj_add_nv_ihex(jsp, jop, "standby_z", !!(buff[4] & 0x1));
+ sgj_add_nv_ihex(jsp, jop, "idle_c", !!(buff[5] & 0x4));
+ sgj_add_nv_ihex(jsp, jop, "idle_b", !!(buff[5] & 0x2));
+ sgj_add_nv_ihex(jsp, jop, "idle_a", !!(buff[5] & 0x1));
+ }
+ sgj_pr_hr_js_vi(jsp, jop, 2, "Stopped condition recovery time (ms)",
+ SGJ_SEP_SPACE_1, sg_get_unaligned_be16(buff + 6));
+ sgj_pr_hr_js_vi(jsp, jop, 2, "Standby_z condition recovery time (ms)",
+ SGJ_SEP_SPACE_1, sg_get_unaligned_be16(buff + 8));
+ sgj_pr_hr_js_vi(jsp, jop, 2, "Standby_y condition recovery time (ms)",
+ SGJ_SEP_SPACE_1, sg_get_unaligned_be16(buff + 10));
+ sgj_pr_hr_js_vi(jsp, jop, 2, "Idle_a condition recovery time (ms)",
+ SGJ_SEP_SPACE_1, sg_get_unaligned_be16(buff + 12));
+ sgj_pr_hr_js_vi(jsp, jop, 2, "Idle_b condition recovery time (ms)",
+ SGJ_SEP_SPACE_1, sg_get_unaligned_be16(buff + 14));
+ sgj_pr_hr_js_vi(jsp, jop, 2, "Idle_c condition recovery time (ms)",
+ SGJ_SEP_SPACE_1, sg_get_unaligned_be16(buff + 16));
+}
+
+int
+filter_json_dev_ids(uint8_t * buff, int len, int m_assoc, struct opts_t * op,
+ sgj_opaque_p jap)
+{
+ int u, off, i_len;
+ sgj_opaque_p jo2p;
+ const uint8_t * bp;
+ sgj_state * jsp = &op->json_st;
+
+ off = -1;
+ while ((u = sg_vpd_dev_id_iter(buff, len, &off, m_assoc, -1, -1)) == 0) {
+ bp = buff + off;
+ i_len = bp[3];
+ if ((off + i_len + 4) > len) {
+ pr2serr(" VPD page error: designator length longer than\n"
+ " remaining response length=%d\n", (len - off));
+ return SG_LIB_CAT_MALFORMED;
+ }
+ jo2p = sgj_new_unattached_object(jsp);
+ sgj_pr_js_designation_descriptor(jsp, jo2p, bp, i_len + 4);
+ sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p);
+ }
+ if (-2 == u) {
+ pr2serr("VPD page error: short designator around offset %d\n", off);
+ return SG_LIB_CAT_MALFORMED;
+ }
+ return 0;
+}
diff --git a/src/sg_vpd_common.h b/src/sg_vpd_common.h
new file mode 100644
index 00000000..485418f3
--- /dev/null
+++ b/src/sg_vpd_common.h
@@ -0,0 +1,205 @@
+#ifndef SG_VPD_H
+#define SG_VPD_H
+
+/*
+ * Copyright (c) 2022 Douglas Gilbert.
+ * All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the BSD_LICENSE file.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "sg_lib.h"
+#include "sg_pr2serr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* standard VPD pages, in ascending page number order */
+#define VPD_SUPPORTED_VPDS 0x0
+#define VPD_UNIT_SERIAL_NUM 0x80
+#define VPD_IMP_OP_DEF 0x81 /* obsolete in SPC-2 */
+#define VPD_ASCII_OP_DEF 0x82 /* obsolete in SPC-2 */
+#define VPD_DEVICE_ID 0x83
+#define VPD_SOFTW_INF_ID 0x84
+#define VPD_MAN_NET_ADDR 0x85
+#define VPD_EXT_INQ 0x86 /* Extended Inquiry */
+#define VPD_MODE_PG_POLICY 0x87
+#define VPD_SCSI_PORTS 0x88
+#define VPD_ATA_INFO 0x89
+#define VPD_POWER_CONDITION 0x8a
+#define VPD_DEVICE_CONSTITUENTS 0x8b
+#define VPD_CFA_PROFILE_INFO 0x8c
+#define VPD_POWER_CONSUMPTION 0x8d
+#define VPD_3PARTY_COPY 0x8f /* 3PC, XCOPY, SPC-4, SBC-3 */
+#define VPD_PROTO_LU 0x90
+#define VPD_PROTO_PORT 0x91
+#define VPD_SCSI_FEATURE_SETS 0x92 /* spc5r11 */
+#define VPD_BLOCK_LIMITS 0xb0 /* SBC-3 */
+#define VPD_SA_DEV_CAP 0xb0 /* SSC-3 */
+#define VPD_OSD_INFO 0xb0 /* OSD */
+#define VPD_BLOCK_DEV_CHARS 0xb1 /* SBC-3 */
+#define VPD_MAN_ASS_SN 0xb1 /* SSC-3, ADC-2 */
+#define VPD_SECURITY_TOKEN 0xb1 /* OSD */
+#define VPD_TA_SUPPORTED 0xb2 /* SSC-3 */
+#define VPD_LB_PROVISIONING 0xb2 /* SBC-3 */
+#define VPD_REFERRALS 0xb3 /* SBC-3 */
+#define VPD_AUTOMATION_DEV_SN 0xb3 /* SSC-3 */
+#define VPD_SUP_BLOCK_LENS 0xb4 /* sbc4r01 */
+#define VPD_DTDE_ADDRESS 0xb4 /* SSC-4 */
+#define VPD_BLOCK_DEV_C_EXTENS 0xb5 /* sbc4r02 */
+#define VPD_LB_PROTECTION 0xb5 /* SSC-5 */
+#define VPD_ZBC_DEV_CHARS 0xb6 /* zbc-r01b */
+#define VPD_BLOCK_LIMITS_EXT 0xb7 /* sbc4r08 */
+#define VPD_FORMAT_PRESETS 0xb8 /* sbc4r18 */
+#define VPD_CON_POS_RANGE 0xb9 /* sbc5r01 */
+#define VPD_NOPE_WANT_STD_INQ -2 /* request for standard inquiry */
+
+enum sg_vpd_invoker_e {
+ SG_VPD_INV_NONE = 0,
+ SG_VPD_INV_SG_INQ,
+ SG_VPD_INV_SG_VPD,
+};
+
+/* This structure holds the union of options available in sg_inq and sg_vpd */
+struct opts_t {
+ enum sg_vpd_invoker_e invoker; /* indicates if for sg_inq or sg_vpd */
+ bool do_all; /* sg_vpd */
+ bool do_ata; /* sg_inq */
+ bool do_decode; /* sg_inq */
+ bool do_descriptors; /* sg_inq */
+ bool do_enum; /* sg_enum */
+ bool do_export; /* sg_inq */
+ bool do_force; /* sg_inq + sg_vpd */
+ bool do_only; /* sg_inq: --only after stdinq: don't fetch VPD page 0x80 */
+ bool do_quiet; /* sg_vpd */
+ bool page_given; /* sg_inq + sg_vpd */
+ bool possible_nvme; /* sg_inq */
+ bool verbose_given; /* sg_inq + sg_vpd */
+ bool version_given; /* sg_inq + sg_vpd */
+ bool do_vpd; /* sg_inq */
+#ifdef SG_SCSI_STRINGS
+ bool opt_new; /* sg_inq */
+#endif
+ int do_block; /* do_block */
+ int do_cmddt; /* sg_inq */
+ int do_help; /* sg_inq */
+ int do_hex; /* sg_inq + sg_vpd */
+ int do_ident; /* sg_vpd */
+ int do_long; /* sg_inq[int] + sg_vpd[bool] */
+ int do_raw; /* sg_inq + sg_vpd */
+ int do_vendor; /* sg_inq */
+ int examine; /* sg_vpd */
+ int inhex_off; /* sg_inq (for decoding multiple VPD pages) */
+ int maxlen; /* sg_inq[was: resp_len] + sg_vpd */
+ int num_pages; /* sg_inq */
+ int page_pdt; /* sg_inq */
+ int vend_prod_num; /* sg_vpd */
+ int verbose; /* sg_inq + sg_vpd */
+ int vpd_pn; /* sg_vpd */
+ const char * device_name; /* sg_inq + sg_vpd */
+ const char * page_str; /* sg_inq + sg_vpd */
+ const char * inhex_fn; /* sg_inq + sg_vpd */
+ const char * vend_prod; /* sg_vpd */
+ sgj_state json_st;
+};
+
+#if 0
+struct opts_t {
+ bool do_ata;
+ bool do_decode;
+ bool do_descriptors;
+ bool do_export;
+ bool do_force;
+ bool do_only; /* --only after standard inq don't fetch VPD page 0x80 */
+ bool verbose_given;
+ bool version_given;
+ bool do_vpd;
+ bool page_given;
+ bool possible_nvme;
+ int do_block;
+ int do_cmddt;
+ int do_help;
+ int do_hex;
+ int do_long;
+ int do_raw;
+ int do_vendor;
+ int verbose;
+ int resp_len;
+ int page_num;
+ int page_pdt;
+ int num_pages;
+ const char * page_arg;
+ const char * device_name;
+ const char * inhex_fn;
+#ifdef SG_SCSI_STRINGS
+ bool opt_new;
+#endif
+};
+#endif
+
+struct svpd_values_name_t {
+ int value; /* VPD page number */
+ int subvalue; /* to differentiate if value+pdt are not unique */
+ int pdt; /* peripheral device type id, -1 is the default */
+ /* (all or not applicable) value */
+ const char * acron;
+ const char * name;
+};
+
+#if 0
+struct svpd_values_name_t {
+ int value;
+ int subvalue;
+ int pdt; /* peripheral device type id, -1 is the default */
+ /* (all or not applicable) value */
+ int vendor; /* vendor flag */
+ const char * acron;
+ const char * name;
+};
+#endif
+
+sgj_opaque_p sg_vpd_js_hdr(sgj_state * jsp, sgj_opaque_p jop,
+ const char * name, const uint8_t * vpd_hdrp);
+void decode_net_man_vpd(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap);
+void decode_x_inq_vpd(uint8_t * b, int len, bool protect, struct opts_t * op,
+ sgj_opaque_p jop);
+void decode_softw_inf_id(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap);
+void decode_mode_policy_vpd(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap);
+void decode_power_condition(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jop);
+int filter_json_dev_ids(uint8_t * buff, int len, int m_assoc,
+ struct opts_t * op, sgj_opaque_p jap);
+const char * pqual_str(int pqual);
+
+void svpd_enumerate_vendor(int vend_prod_num);
+int svpd_count_vendor_vpds(int vpd_pn, int vend_prod_num);
+int svpd_decode_vendor(int sg_fd, struct opts_t * op, int off);
+const struct svpd_values_name_t * svpd_find_vendor_by_acron(const char * ap);
+int svpd_find_vp_num_by_acron(const char * vp_ap);
+const struct svpd_values_name_t * svpd_find_vendor_by_num(int page_num,
+ int vend_prod_num);
+int vpd_fetch_page(int sg_fd, uint8_t * rp, int page, int mxlen,
+ bool qt, int vb, int * rlenp);
+void dup_sanity_chk(int sz_opts_t, int sz_values_name_t);
+
+extern uint8_t * rsp_buff;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of SG_VPD_H */
diff --git a/src/sg_vpd_vendor.c b/src/sg_vpd_vendor.c
index 1a607404..2f9dc10f 100644
--- a/src/sg_vpd_vendor.c
+++ b/src/sg_vpd_vendor.c
@@ -28,7 +28,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-#include "sg_vpd.h"
+#include "sg_vpd_common.h"
/* This is a companion file to sg_vpd.c . It contains logic to output and
decode vendor specific VPD pages
diff --git a/testing/tst_sg_lib.c b/testing/tst_sg_lib.c
index 2f44d2fe..e3cba30a 100644
--- a/testing/tst_sg_lib.c
+++ b/testing/tst_sg_lib.c
@@ -44,7 +44,7 @@
* related to snprintf().
*/
-static const char * version_str = "1.15 20220625";
+static const char * version_str = "1.16 20220710";
#define MY_NAME "tst_sg_lib"
@@ -357,8 +357,8 @@ main(int argc, char * argv[])
++did_something;
if (as_json) {
jo2p = sgj_new_named_object(jsp, jop, "desc_sense_data__test1");
- sgj_get_sense(jsp, jo2p, desc_sense_data1,
- (int)sizeof(desc_sense_data1));
+ sgj_pr_js_sense(jsp, jo2p, desc_sense_data1,
+ (int)sizeof(desc_sense_data1));
} else {
printf("desc_sense_data test1:\n");
sg_print_sense(leadin, desc_sense_data1,
@@ -383,8 +383,8 @@ main(int argc, char * argv[])
#endif
if (as_json) {
jo2p = sgj_new_named_object(jsp, jop, "desc_sense_data__test2");
- sgj_get_sense(jsp, jo2p, desc_sense_data2,
- (int)sizeof(desc_sense_data2));
+ sgj_pr_js_sense(jsp, jo2p, desc_sense_data2,
+ (int)sizeof(desc_sense_data2));
} else {
printf("desc_sense_data test2\n");
sg_print_sense(leadin, desc_sense_data2,
@@ -394,8 +394,8 @@ main(int argc, char * argv[])
if (as_json) {
jo2p = sgj_new_named_object(jsp, jop,
"desc_sense_block_combo_test3");
- sgj_get_sense(jsp, jo2p, desc_sense_data3,
- (int)sizeof(desc_sense_data3));
+ sgj_pr_js_sense(jsp, jo2p, desc_sense_data3,
+ (int)sizeof(desc_sense_data3));
} else {
printf("desc_sense block dev combo plus designator test3\n");
sg_print_sense(leadin, desc_sense_data3,
@@ -405,8 +405,8 @@ main(int argc, char * argv[])
if (as_json) {
jo2p = sgj_new_named_object(jsp, jop,
"desc_sense_forwarded_sense_test4");
- sgj_get_sense(jsp, jo2p, desc_sense_data4,
- (int)sizeof(desc_sense_data4));
+ sgj_pr_js_sense(jsp, jo2p, desc_sense_data4,
+ (int)sizeof(desc_sense_data4));
} else {
printf("desc_sense forwarded sense test4\n");
sg_print_sense(leadin, desc_sense_data4,
@@ -416,8 +416,8 @@ main(int argc, char * argv[])
if (as_json) {
jo2p = sgj_new_named_object(jsp, jop,
"desc_sense_ata_info_test5");
- sgj_get_sense(jsp, jo2p, desc_sense_data5,
- (int)sizeof(desc_sense_data5));
+ sgj_pr_js_sense(jsp, jo2p, desc_sense_data5,
+ (int)sizeof(desc_sense_data5));
} else {
printf("desc_sense ATA Info test5\n");
sg_print_sense(leadin, desc_sense_data5,
@@ -427,8 +427,8 @@ main(int argc, char * argv[])
if (as_json) {
jo2p = sgj_new_named_object(jsp, jop,
"desc_sense_ua_binding_test6");
- sgj_get_sense(jsp, jo2p, desc_sense_data6,
- (int)sizeof(desc_sense_data6));
+ sgj_pr_js_sense(jsp, jo2p, desc_sense_data6,
+ (int)sizeof(desc_sense_data6));
} else {
printf("desc_sense UA subsidiary binding changed test6\n");
sg_print_sense(leadin, desc_sense_data6,