aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2022-07-06 04:42:32 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2022-07-06 04:42:32 +0000
commit5e6f4a6ba05f122b39407f2bdb8d8bea194b8990 (patch)
treedef2dad0393b47310771ff034b74a6a189e862e4
parent1861523da54dbb1dac823f754156e7e67f2768cb (diff)
downloadsg3_utils-5e6f4a6ba05f122b39407f2bdb8d8bea194b8990.tar.gz
sg_vpd: more JSON work
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@958 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog2
-rw-r--r--doc/sg3_utils_json.843
-rw-r--r--doc/sg_modes.810
-rw-r--r--doc/sg_persist.811
-rw-r--r--include/sg_pr2serr.h35
-rw-r--r--inhex/vpd_sdeb.hex99
-rw-r--r--lib/sg_pr2serr.c145
-rw-r--r--src/sg_decode_sense.c4
-rw-r--r--src/sg_inq.c2
-rw-r--r--src/sg_inq_data.c2
-rw-r--r--src/sg_opcodes.c2
-rw-r--r--src/sg_vpd.c649
-rw-r--r--src/sg_vpd.h1
-rw-r--r--testing/tst_sg_lib.c4
14 files changed, 701 insertions, 308 deletions
diff --git a/ChangeLog b/ChangeLog
index 05c629eb..800c2e01 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 [20220701] [svn: r957]
+Changelog for pre-release sg3_utils-1.48 [20220705] [svn: r958]
- some utilities: add experimental --json[=JO] option
- sg_z_act_query: new utility for sending either a
Zone activate or Zone query command
diff --git a/doc/sg3_utils_json.8 b/doc/sg3_utils_json.8
index 8ada8146..454dfa7a 100644
--- a/doc/sg3_utils_json.8
+++ b/doc/sg3_utils_json.8
@@ -15,14 +15,17 @@ output, rather than simple, human-readable output. The default remains
human-readable output.
.PP
JSON is an open standard file format that can be used for data exchange
-between systems. See https://en.wikipedia.org/wiki/JSON . JSON comes in
-many flavours and this one uses the json-builder C implementation found
-at https://github.com/json-parser/json-builder which implements four simple
-JSON data types: string, integer, boolean and null. Its other data types
-are JSON object and JSON array. This project uses the "snake" convention
-for JSON object names: all in lower case with separate words joined with
-a single underscore (e.g. "starting_lba"). The json-builder library uses
-the SPDX-License-Identifier: BSD-2-Clause which is the same license as the
+between systems. See https://en.wikipedia.org/wiki/JSON . JSON comes in many
+flavours and this one uses the json-builder C implementation found at
+https://github.com/json-parser/json-builder which implements four simple JSON
+data types: string, integer, boolean and null. Its other data types are JSON
+object and JSON array.
+.PP
+This project uses the "snake_case" convention for JSON object names: all in
+lower case letters or numerals with individual words joined with a single
+underscore (e.g. "starting_lba"). There should be no leading or trailing
+underscore characters. The json-builder library uses the
+SPDX\-License\-Identifier: BSD\-2\-Clause which is the same license as the
bulk of the utilities in the sg3_utils package.
.PP
The json-builder library is relatively lightweight (700 lines of C code) and
@@ -45,7 +48,7 @@ This manpage discusses the \fI\-\-json\fR option which may or may not itself
have an optional argument. In its shorter form it may either be \fI\-j\fR or
\fI\-J\fR (lower case preferred if not already in use). The shorter form may
also take an argument but there must not be a space (or whitespace) between
-\fI\-j\fR and that argument.
+\fI\-j\fR and that argument.
.SH ENVIRONMENT VARIABLES
The SG3_UTILS_JSON_OPTS environment variable allows the user to override the
default values of the \fIJO\fR settings. Those settings can again be overridden
@@ -105,6 +108,10 @@ 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
@@ -126,7 +133,20 @@ control character is active most (non\-trivial) fields that have an integer
value instead receive a a sub\-object containing at least a "i" field with
the integer value and a "hex" field with the corresponding hex value in a
JSON string. That hex string has no hex decorations (i.e. no leading '0x'
-nor traing 'h').
+nor trailing 'h').
+.br
+This boolean control character is default off (false).
+.TP
+\fBk\fR
+this is a boolean control character for finer control of non\-pretty printed
+JSON output. If the 'p' control character is set on (true) then this option
+has no effect.
+.br
+If the 'p' control character is set off (false) and this control character is
+set off (false) then the single line JSON output contains some spaces for
+readability. If the 'p' control character is set off (false) and this control
+character is set on (true) then the JSON single line JSON output is "packed"
+removing all unnecessary spaces.
.br
This boolean control character is default off (false).
.TP
@@ -163,6 +183,9 @@ have their name on a separate line. These lines are indented with the
current tab setting to indicate the level of nesting. Basically the pretty
printed form is for human consumption.
.br
+There are two forms of non\-pretty printed output, see the "packed" control
+character ['k'].
+.br
This boolean control character is default on (true).
.TP
\fBs\fR
diff --git a/doc/sg_modes.8 b/doc/sg_modes.8
index 162f5f93..4fef24ad 100644
--- a/doc/sg_modes.8
+++ b/doc/sg_modes.8
@@ -1,4 +1,4 @@
-.TH SG_MODES "8" "September 2020" "sg3_utils\-1.45" SG3_UTILS
+.TH SG_MODES "8" "July 2022" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_modes \- reads mode pages with SCSI MODE SENSE command
.SH SYNOPSIS
@@ -20,9 +20,9 @@ sg_modes \- reads mode pages with SCSI MODE SENSE command
This utility sends a MODE SENSE SCSI command to the \fIDEVICE\fR and
outputs the response. There is a 6 byte and 10 byte (cdb) variant of the
MODE SENSE command, this utility defaults to the 10 byte variant. The SPC\-4
-standard (and SPC\-5 drafts) include a note stating that implementers should
-migrate away from the SCSI MODE SELECT(6) and MODE SENSE(6) commands in
-favour of the 10 byte variants (e.g. MODE SENSE(10)).
+standard (and the SPC\-5 standard) include a note stating that implementers
+should migrate away from the SCSI MODE SELECT(6) and MODE SENSE(6) commands
+in favour of the 10 byte variants (e.g. MODE SENSE(10)).
.PP
This utility decodes mode page headers and block descriptors but outputs
the contents of each mode page in hex. It also has no facility to change
@@ -301,7 +301,7 @@ Written by Douglas Gilbert
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2000\-2020 Douglas Gilbert
+Copyright \(co 2000\-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.
diff --git a/doc/sg_persist.8 b/doc/sg_persist.8
index 36d784b9..23a0c97a 100644
--- a/doc/sg_persist.8
+++ b/doc/sg_persist.8
@@ -35,11 +35,10 @@ READ RESERVATION, REPORT CAPABILITIES and READ FULL STATUS.
.PP
Before trying to change Persistent reservations and registrations users
should be aware of what they are doing. The relevant sections of the SCSI
-Primary Commands document (i.e. SPC\-5 whose most recent draft is revision
-18 dated 4 January 2018) are sections 5.14 (titled "Reservations"),
-6.16 (for the PRIN command) and 6.17 (for the PROUT command). To safeguard
-against accidental use, the \fI\-\-out\fR option must be given when a
-PROUT sub\-command (e.g. \fI\-\-register\fR) is used.
+Primary Commands document (i.e. SPC\-5 ANSI INCITS 502\-2020) are sections
+8.14 (titled "Reservations"), 9.16 (for the PRIN command) and 9.17 (for the
+PROUT command). To safeguard against accidental use, the \fI\-\-out\fR option
+must be given when a PROUT sub\-command (e.g. \fI\-\-register\fR) is used.
.PP
The older SCSI RESERVE and RELEASE commands (both 6 and 10 byte variants)
are not supported by this utility. In SPC\-3, RESERVE and RELEASE are
@@ -245,7 +244,7 @@ and \fI\-\-param\-rk=RK\fR options must also be specified.
\fB\-X\fR, \fB\-\-transport\-id\fR=\fITIDS\fR
The \fITIDS\fR argument can take one of several forms. It can be a
comma (or single space) separated list of ASCII hex bytes representing
-a single TransportID as defined in SPC\-4. They are usually 24 bytes
+a single TransportID as defined in SPC\-5. They are usually 24 bytes
long apart from in iSCSI. The \fITIDS\fR argument may be a transport
specific form (e.g. "sas,5000c50005b32001" is clearer than an equivalent
to the hex byte form: "6,0,0,0,5,0,c5,0,5,b3,20,1"). The \fITIDS\fR argument
diff --git a/include/sg_pr2serr.h b/include/sg_pr2serr.h
index 43a85e05..23cad944 100644
--- a/include/sg_pr2serr.h
+++ b/include/sg_pr2serr.h
@@ -73,7 +73,8 @@ typedef struct sgj_state_t {
bool pr_exit_status; /* 'e' (def: true) */
bool pr_hex; /* 'h' (def: false) */
bool pr_leadin; /* 'l' (def: true) */
- bool pr_output; /* 'o' (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) */
bool pr_string; /* 's' (def: true) */
char pr_format; /* (def: '\0') */
@@ -82,17 +83,17 @@ typedef struct sgj_state_t {
/* the following hold state information */
int first_bad_char; /* = '\0' */
sgj_opaque_p basep; /* base JSON object pointer */
- sgj_opaque_p outputp; /* 'output' named JSON array pointer */
+ sgj_opaque_p out_hrp; /* JSON array pointer when pr_out_hr set */
sgj_opaque_p userp; /* for temporary usage */
} sgj_state;
/* If jsp in non-NULL and jsp->pr_as_json is true then this call is ignored
- * unless jsp->pr_output is true. Otherwise this function prints to stdout
- * like printf(fmt, ...); note that no LF is added. In the jsp->pr_output
- * is true case, nothing is printed to stdout but instead is placed into the
- * JSON 'output' array (jsp->outputp) after some preprocessing. That
- * preprocessing involves removing a leading LF from 'fmt' (if present) and
- * up to two trailing LF characters. */
+ * 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
+ * true case, nothing is printed to stdout but instead is placed into a JSON
+ * array (jsp->out_hrp) after some preprocessing. That preprocessing involves
+ * removing a leading LF from 'fmt' (if present) and up to two trailing LF
+ * characters. */
void sgj_pr_hr(sgj_state * jsp, const char * fmt, ...) __printf(2, 3);
/* Initializes the state object pointed to by jsp based on the argument
@@ -110,7 +111,7 @@ bool sgj_init_state(sgj_state * jsp, const char * j_optarg);
* in-core tree. If jsp is NULL nothing further happens. Otherwise the pointer
* to be returned is placed in jsp->basep. If jsp->pr_leadin is true and
* util_name is non-NULL then a "utility_invoked" JSON object is made with
- * "name", and "version_date" object fields. If the jsp->pr_output field is
+ * "name", and "version_date" object fields. If the jsp->pr_out_hr field is
* true a named array called "output" is added to the "utility_invoked" object
* (creating it in the case when jsp->pr_leadin is false) and a pointer to
* that array object is placed in jsp->objectp . The returned pointer is not
@@ -134,6 +135,8 @@ sgj_opaque_p sgj_new_unattached_array(sgj_state * jsp);
* and if not, used. */
sgj_opaque_p sgj_new_named_object(sgj_state * jsp, sgj_opaque_p jop,
const char * name);
+sgj_opaque_p sgj_new_snake_named_object(sgj_state * jsp, sgj_opaque_p jop,
+ const char * conv2sname);
/* If jsp is NULL or jsp->pr_as_json is false nothing happens and NULL is
* returned. Otherwise it creates a new named object (whose name is what
@@ -143,6 +146,8 @@ sgj_opaque_p sgj_new_named_object(sgj_state * jsp, sgj_opaque_p jop,
* and if not, used. */
sgj_opaque_p sgj_new_named_array(sgj_state * jsp, sgj_opaque_p jop,
const char * name);
+sgj_opaque_p sgj_new_snake_named_array(sgj_state * jsp, sgj_opaque_p jop,
+ const char * conv2sname);
/* If either jsp or value is NULL or jsp->pr_as_json is false then nothing
* happens and NULL is returned. The insertion point is at jop but if it is
@@ -190,9 +195,9 @@ sgj_opaque_p sgj_add_nv_o(sgj_state * jsp, sgj_opaque_p jop,
const char * name, sgj_opaque_p ua_jop);
/* The '_hr_js_' refers to generating output both for human readable and/or
- * JSON with a single invocation. If jsp is non_NULL and jsp->pr_output is
+ * JSON with a single invocation. If jsp is non_NULL and jsp->pr_out_hr is
* true then both JSON and human readable output is formed (and the latter is
- * placed in the jsp->outputp JSON array). The human readable form will have
+ * placed in the jsp->out_hrp JSON array). The human readable form will have
* leadin_sp spaces followed by 'name' then a separator, then 'value' with a
* trailing LF. If 'name' is NULL then it and the separator are ignored. If
* there is JSON output, then leadin_sp and sep are ignored. If 'jop' is NULL
@@ -260,10 +265,10 @@ void sgj_add_nv_ihexstr_ane(sgj_state * jsp, sgj_opaque_p jop,
const char * ane_s);
/* Breaks up the string pointed to by 'sp' into lines and adds them to the
- * jsp->outputp array. Treat '\n' in sp as line breaks. Consumes characters
+ * jsp->out_hrp array. Treat '\n' in sp as line breaks. Consumes characters
* from sp until either a '\0' is found or slen is exhausted. Add each line
- * to jsp->outputp JSON array (if conditions met). */
-void sgj_pr_str_output(sgj_state * jsp, const char * sp, int slen);
+ * to jsp->out_hrp JSON array (if conditions met). */
+void sgj_pr_str_out_hr(sgj_state * jsp, const char * sp, int slen);
/* This function only produces JSON output if jsp is non-NULL and
* jsp->pr_as_json is true. 'sbp' is assumed to point to sense data as
@@ -292,7 +297,7 @@ void sgj_free_unattached(sgj_opaque_p jop);
/* If jsp is NULL or jsp->basep is NULL then this function does nothing.
* This function does bottom up, heap freeing of all the in-core JSON
* objects and arrays attached to the root JSON object assumed to be
- * found at jsp->basep . After this call jsp->basep, jsp->outputp and
+ * found at jsp->basep . After this call jsp->basep, jsp->out_hrp and
* jsp->userp will all be set to NULL. */
void sgj_finish(sgj_state * jsp);
diff --git a/inhex/vpd_sdeb.hex b/inhex/vpd_sdeb.hex
new file mode 100644
index 00000000..ba5cd4ee
--- /dev/null
+++ b/inhex/vpd_sdeb.hex
@@ -0,0 +1,99 @@
+#
+# The VPD responses in this file where generated from a dummy device
+# (ramdisk) associated with the Linux scsi_debug driver as follows:
+# sg_vpd -a /dev/sg0 -HHHH
+
+# Supported VPD pages VPD page
+00 00 00 0c 00 80 83 84 85 86 87 88 89 b0 b1 b2
+
+# Unit serial number VPD page
+00 80 00 04 32 30 30 30
+
+# Device identification VPD page
+00 83 00 70 02 01 00 1c 4c 69 6e 75 78 20 20 20
+73 63 73 69 5f 64 65 62 75 67 20 20 20 20 20 20
+32 30 30 30 01 03 00 08 33 33 33 30 00 00 07 d0
+61 94 00 04 00 00 00 01 61 93 00 08 32 22 22 20
+00 00 07 ce 61 95 00 04 00 00 01 00 61 a3 00 08
+32 22 22 20 00 00 07 cd 63 a8 00 18 6e 61 61 2e
+33 32 32 32 32 32 32 30 30 30 30 30 30 37 43 44
+00 00 00 00
+
+# Software interface identification VPD page
+00 84 00 12 22 22 22 00 bb 00 22 22 22 00 bb 01
+22 22 22 00 bb 02
+
+# Management network addresses VPD page
+00 85 00 44 01 00 00 20 68 74 74 70 73 3a 2f 2f
+77 77 77 2e 6b 65 72 6e 65 6c 2e 6f 72 67 2f 63
+6f 6e 66 69 67 00 00 00 04 00 00 1c 68 74 74 70
+3a 2f 2f 77 77 77 2e 6b 65 72 6e 65 6c 2e 6f 72
+67 2f 6c 6f 67 00 00 00
+
+# extended INQUIRY data VPD page
+00 86 00 3c 00 07 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+# Mode page policy VPD page
+00 87 00 08 02 00 80 00 18 00 82 00
+
+# SCSI Ports VPD page
+00 88 00 30 00 00 00 01 00 00 00 00 00 00 00 0c
+61 93 00 08 32 22 22 20 00 00 07 ce 00 00 00 02
+00 00 00 00 00 00 00 0c 61 93 00 08 32 22 22 20
+00 00 07 cf
+
+# ATA information VPD page
+00 89 02 38 00 00 00 00 6c 69 6e 75 78 20 20 20
+53 41 54 20 73 63 73 69 5f 64 65 62 75 67 20 20
+31 32 33 34 34 00 00 00 01 00 00 00 00 00 00 00
+01 00 00 00 00 00 00 00 ec 00 00 00 5a 0c ff 3f
+37 c8 10 00 00 00 00 00 3f 00 00 00 00 00 00 00
+58 58 58 58 58 58 58 58 20 20 20 20 20 20 20 20
+20 20 20 20 00 00 00 40 04 00 2e 33 38 31 20 20
+20 20 54 53 38 33 30 30 33 31 53 41 20 20 20 20
+20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
+20 20 20 20 20 20 20 20 20 20 10 80 00 00 00 2f
+00 00 00 02 00 02 07 00 ff ff 01 00 3f 00 c1 ff
+3e 00 10 01 b0 f8 50 09 00 00 07 00 03 00 78 00
+78 00 f0 00 78 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 02 00 00 00 00 00 00 00 7e 00 1b 00
+6b 34 01 7d 03 40 69 34 01 3c 03 40 7f 40 00 00
+00 00 fe fe 00 00 00 00 00 fe 00 00 00 00 00 00
+00 00 00 00 b0 f8 50 09 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 01 00 b0 f8
+50 09 b0 f8 50 09 20 20 02 00 b6 42 00 80 8a 00
+06 3c 0a 3c ff ff c6 07 00 01 00 08 f0 0f 00 10
+02 00 30 00 00 00 00 00 00 00 06 fe 00 00 02 00
+50 00 8a 00 4f 95 00 00 21 00 0b 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 a5 51
+
+# Block limits VPD page
+00 b0 00 3c 00 00 00 01 00 00 40 00 00 00 04 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
+00 00 00 00 00 00 00 00 00 00 ff ff 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+# Block device characteristics VPD page
+00 b1 00 3c 00 01 00 05 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+# Logical block provisioning VPD page
+00 b2 00 04 00 00 00 00
diff --git a/lib/sg_pr2serr.c b/lib/sg_pr2serr.c
index be07a2e1..310ea78b 100644
--- a/lib/sg_pr2serr.c
+++ b/lib/sg_pr2serr.c
@@ -49,6 +49,8 @@ static const json_serialize_opts def_out_settings = {
4 /* indent size */
};
+static int sgj_name_to_snake(const char * in, char * out, int maxlen_out);
+
/* Users of the sg_pr2serr.h header need this function definition */
int
@@ -116,11 +118,14 @@ sgj_parse_opts(sgj_state * jsp, const char * j_optarg)
case 'h':
jsp->pr_hex = ! prev_negate;
break;
+ case 'k':
+ jsp->pr_packed = ! prev_negate;
+ break;
case 'l':
jsp->pr_leadin = ! prev_negate;
break;
case 'o':
- jsp->pr_output = ! prev_negate;
+ jsp->pr_out_hr = ! prev_negate;
break;
case 'p':
jsp->pr_pretty = ! prev_negate;
@@ -178,6 +183,8 @@ sg_json_usage(int char_if_not_j, char * b, int blen)
n += sg_scnpr(b + n, blen - n,
" h show 'hex' fields\n");
n += sg_scnpr(b + n, blen - n,
+ " k packed, only non-pretty printed output\n");
+ n += sg_scnpr(b + n, blen - n,
" l show lead-in fields (invocation "
"information)\n");
n += sg_scnpr(b + n, blen - n,
@@ -212,11 +219,12 @@ fini:
char *
sg_json_settings(sgj_state * jsp, char * b, int blen)
{
- snprintf(b, blen, "%d%sa%se%sh%sl%so%sp%ss%sv", jsp->pr_indent_size,
+ 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_leadin ? "" : "-",
- jsp->pr_output ? "" : "-", jsp->pr_pretty ? "" : "-",
- jsp->pr_string ? "" : "-", jsp->verbose ? "" : "-");
+ jsp->pr_hex ? "" : "-", jsp->pr_packed ? "" : "-",
+ jsp->pr_leadin ? "" : "-", jsp->pr_out_hr ? "" : "-",
+ jsp->pr_pretty ? "" : "-", jsp->pr_string ? "" : "-",
+ jsp->verbose ? "" : "-");
return b;
}
@@ -228,7 +236,8 @@ sgj_def_opts(sgj_state * jsp)
jsp->pr_exit_status = true;
jsp->pr_hex = false;
jsp->pr_leadin = true;
- jsp->pr_output = false;
+ jsp->pr_out_hr = false;
+ jsp->pr_packed = false; /* 'k' control character, needs '-p' */
jsp->pr_pretty = true;
jsp->pr_string = true;
jsp->pr_format = 0;
@@ -244,7 +253,7 @@ sgj_init_state(sgj_state * jsp, const char * j_optarg)
sgj_def_opts(jsp);
jsp->basep = NULL;
- jsp->outputp = NULL;
+ jsp->out_hrp = NULL;
jsp->userp = NULL;
cp = getenv(sgj_opts_ev);
@@ -286,8 +295,11 @@ sgj_start(const char * util_name, const char * ver_str, int argc,
(json_value *)jap);
if (util_name) {
jap = json_array_new(0);
- for (k = 0; k < argc; ++k)
- json_array_push((json_value *)jap, json_string_new(argv[k]));
+ if (argv) {
+ for (k = 0; k < argc; ++k)
+ json_array_push((json_value *)jap,
+ json_string_new(argv[k]));
+ }
jv2p = json_object_push((json_value *)jvp, "utility_invoked",
json_object_new(0));
json_object_push((json_value *)jv2p, "name",
@@ -313,19 +325,19 @@ sgj_start(const char * util_name, const char * ver_str, int argc,
json_string_new(b));
}
} else {
- if (jsp->pr_output && util_name)
+ if (jsp->pr_out_hr && util_name)
jv2p = json_object_push((json_value *)jvp, "utility_invoked",
json_object_new(0));
}
- if (jsp->pr_output && jv2p) {
- jsp->outputp = json_object_push((json_value *)jv2p, "output",
+ if (jsp->pr_out_hr && jv2p) {
+ jsp->out_hrp = json_object_push((json_value *)jv2p, "output",
json_array_new(0));
if (jsp->pr_leadin && (jsp->verbose > 3)) {
char * bp = (char *)calloc(4096, 1);
if (bp) {
sg_json_usage(0, bp, 4096);
- sgj_pr_str_output(jsp, bp, strlen(bp));
+ sgj_pr_str_out_hr(jsp, bp, strlen(bp));
free(bp);
}
}
@@ -359,7 +371,8 @@ sgj_pr2file(sgj_state * jsp, sgj_opaque_p jop, int exit_status, FILE * fp)
if (jsp->pr_indent_size != def_out_settings.indent_size)
out_settings.indent_size = jsp->pr_indent_size;
if (! jsp->pr_pretty)
- out_settings.mode = json_serialize_mode_single_line;
+ out_settings.mode = jsp->pr_packed ? json_serialize_mode_packed :
+ json_serialize_mode_single_line;
len = json_measure_ex(jvp, out_settings);
if (len < 1)
@@ -372,6 +385,7 @@ sgj_pr2file(sgj_state * jsp, sgj_opaque_p jop, int exit_status, FILE * fp)
pr2serr("%s: unable to get %zu bytes on heap\n", __func__, len);
return;
}
+
json_serialize_ex(b, jvp, out_settings);
if (jsp->verbose > 3)
fprintf(fp, "json serialized:\n");
@@ -384,7 +398,7 @@ sgj_finish(sgj_state * jsp)
if (jsp && jsp->basep) {
json_builder_free((json_value *)jsp->basep);
jsp->basep = NULL;
- jsp->outputp = NULL;
+ jsp->out_hrp = NULL;
jsp->userp = NULL;
}
}
@@ -401,7 +415,7 @@ sgj_pr_hr(sgj_state * jsp, const char * fmt, ...)
{
va_list args;
- if (jsp->pr_as_json && jsp->pr_output) {
+ if (jsp->pr_as_json && jsp->pr_out_hr) {
size_t len;
char b[256];
@@ -420,7 +434,7 @@ sgj_pr_hr(sgj_state * jsp, const char * fmt, ...)
/* remove leading linefeed, if present */
if ((len > 0) && ('\n' == b[0]))
++cp;
- json_array_push((json_value *)jsp->outputp, json_string_new(cp));
+ json_array_push((json_value *)jsp->out_hrp, json_string_new(cp));
}
va_end(args);
} else if (jsp->pr_as_json) {
@@ -445,6 +459,22 @@ sgj_new_named_object(sgj_state * jsp, sgj_opaque_p jop, const char * name)
return resp;
}
+sgj_opaque_p
+sgj_new_snake_named_object(sgj_state * jsp, sgj_opaque_p jop,
+ const char * conv2sname)
+{
+ if (jsp && jsp->pr_as_json && conv2sname) {
+ int olen = strlen(conv2sname);
+ char * sname = malloc(olen + 8);
+ int nlen = sgj_name_to_snake(conv2sname, sname, olen + 8);
+
+ if (nlen > 0)
+ return json_object_push((json_value *)(jop ? jop : jsp->basep),
+ sname, json_object_new(0));
+ }
+ return NULL;
+}
+
/* jop will 'own' returned value (if non-NULL) */
sgj_opaque_p
sgj_new_named_array(sgj_state * jsp, sgj_opaque_p jop, const char * name)
@@ -457,6 +487,22 @@ sgj_new_named_array(sgj_state * jsp, sgj_opaque_p jop, const char * name)
return resp;
}
+sgj_opaque_p
+sgj_new_snake_named_array(sgj_state * jsp, sgj_opaque_p jop,
+ const char * conv2sname)
+{
+ if (jsp && jsp->pr_as_json && conv2sname) {
+ int olen = strlen(conv2sname);
+ char * sname = malloc(olen + 8);
+ int nlen = sgj_name_to_snake(conv2sname, sname, olen + 8);
+
+ if (nlen > 0)
+ return json_object_push((json_value *)(jop ? jop : jsp->basep),
+ sname, json_array_new(0));
+ }
+ return NULL;
+}
+
/* Newly created object is un-attached to jsp->basep tree */
sgj_opaque_p
sgj_new_unattached_object(sgj_state * jsp)
@@ -490,14 +536,19 @@ sgj_opaque_p
sgj_add_nv_s_len(sgj_state * jsp, sgj_opaque_p jop, const char * name,
const char * value, int slen)
{
+ int k;
+
if (jsp && jsp->pr_as_json && value && (slen >= 0)) {
+ for (k = 0; k < slen; ++k) { /* don't want '\0' in value string */
+ if (0 == value[k])
+ break;
+ }
if (name)
return json_object_push((json_value *)(jop ? jop : jsp->basep),
- name, json_string_new_length(slen,
- value));
+ name, json_string_new_length(k, value));
else
return json_array_push((json_value *)(jop ? jop : jsp->basep),
- json_string_new_length(slen, value));
+ json_string_new_length(k, value));
} else
return NULL;
}
@@ -555,8 +606,7 @@ sgj_add_nv_ihex(sgj_state * jsp, sgj_opaque_p jop, const char * name,
if ((NULL == jsp) || (NULL == name) || (! jsp->pr_as_json))
return;
else if (jsp->pr_hex) {
- sgj_opaque_p jo2p =
- sgj_new_named_object(jsp, jop, name);
+ sgj_opaque_p jo2p = sgj_new_named_object(jsp, jop, name);
char b[64];
if (NULL == jo2p)
@@ -577,8 +627,8 @@ sgj_add_nv_istr(sgj_state * jsp, sgj_opaque_p jop, const char * name,
if ((NULL == jsp) || (! jsp->pr_as_json))
return;
else if (jsp->pr_string) {
- sgj_opaque_p jo2p =
- sgj_new_named_object(jsp, jop, name);
+ sgj_opaque_p jo2p = sgj_new_named_object(jsp, jop, name);
+
if (NULL == jo2p)
return;
sgj_add_nv_i(jsp, jo2p, "i", (int64_t)val_i);
@@ -598,8 +648,7 @@ sgj_add_nv_ihexstr(sgj_state * jsp, sgj_opaque_p jop, const char * name,
sgj_add_nv_i(jsp, jop, name, val_i);
else {
char b[64];
- sgj_opaque_p jo2p =
- sgj_new_named_object(jsp, jop, name);
+ sgj_opaque_p jo2p = sgj_new_named_object(jsp, jop, name);
if (NULL == jo2p)
return;
@@ -713,18 +762,18 @@ sgj_add_nv_ihexstr_ane(sgj_state * jsp, sgj_opaque_p jop, const char * name,
}
/* Treat '\n' in sp as line breaks. Consumes characters from sp until either
- * a '\0' is found or slen is exhausted. Add each line to jsp->outputp JSON
+ * a '\0' is found or slen is exhausted. Add each line to jsp->out_hrp JSON
* array (if conditions met). */
void
-sgj_pr_str_output(sgj_state * jsp, const char * sp, int slen)
+sgj_pr_str_out_hr(sgj_state * jsp, const char * sp, int slen)
{
char c;
int k, n;
const char * prev_sp = sp;
const char * cur_sp = sp;
- if ((NULL == jsp) || (NULL == jsp->outputp) || (! jsp->pr_as_json) ||
- (! jsp->pr_output))
+ if ((NULL == jsp) || (NULL == jsp->out_hrp) || (! jsp->pr_as_json) ||
+ (! jsp->pr_out_hr))
return;
for (k = 0; k < slen; ++k, ++cur_sp) {
c = *cur_sp;
@@ -732,20 +781,25 @@ sgj_pr_str_output(sgj_state * jsp, const char * sp, int slen)
break;
else if ('\n' == c) {
n = cur_sp - prev_sp;
- /* when name is NULL, add to array (jsp->outputp) */
- sgj_add_nv_s_len(jsp, jsp->outputp, NULL, prev_sp, n);
+ /* when name is NULL, add to array (jsp->out_hrp) */
+ sgj_add_nv_s_len(jsp, jsp->out_hrp, NULL, prev_sp, n);
prev_sp = cur_sp + 1;
}
}
if (prev_sp < cur_sp) {
n = cur_sp - prev_sp;
- sgj_add_nv_s_len(jsp, jsp->outputp, NULL, prev_sp, n);
+ sgj_add_nv_s_len(jsp, jsp->out_hrp, NULL, prev_sp, n);
}
}
-/* Returns number of characters placed in 'out' excluding trailing NULL */
+/* 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 */
static int
-sgj_jsonify_name(const char * in, char * out, int maxlen_out)
+sgj_name_to_snake(const char * in, char * out, int maxlen_out)
{
bool prev_underscore = false;
int c, k, j, inlen;
@@ -800,7 +854,7 @@ sgj_pr_hr_js_xx(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
b[n] = ' ';
b[n] = '\0';
if (NULL == name) {
- if ((! as_json) || (jsp && jsp->pr_output)) {
+ if ((! as_json) || (jsp && jsp->pr_out_hr)) {
switch (jtype) {
case json_string:
sg_scnpr(b + n, blen - n, "%s", jvp->u.string.ptr);
@@ -819,9 +873,9 @@ sgj_pr_hr_js_xx(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
printf("%s\n", b);
}
if (NULL == jop) {
- if (as_json && jsp->pr_output) {
+ if (as_json && jsp->pr_out_hr) {
eaten = true;
- json_array_push((json_value *)jsp->outputp,
+ json_array_push((json_value *)jsp->out_hrp,
jvp ? jvp : json_null_new());
}
} else { /* assume jop points to named array */
@@ -841,14 +895,14 @@ sgj_pr_hr_js_xx(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
if (NULL == jop)
jop = jsp->basep;
- k = sgj_jsonify_name(name, jname, sizeof(jname));
+ 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_output) || (! as_json))) {
+ if (jvp && ((as_json && jsp->pr_out_hr) || (! as_json))) {
switch (sep) {
case SGJ_SEP_NONE:
break;
@@ -894,8 +948,8 @@ sgj_pr_hr_js_xx(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
break;
}
}
- if (as_json && jsp->pr_output)
- json_array_push((json_value *)jsp->outputp, json_string_new(b));
+ if (as_json && jsp->pr_out_hr)
+ json_array_push((json_value *)jsp->out_hrp, json_string_new(b));
else if (! as_json)
printf("%s\n", b);
if (jvp && (! eaten))
@@ -1292,7 +1346,7 @@ sgj_uds_referral_descriptor(sgj_state * jsp, sgj_opaque_p jop,
"Not all referrals");
dp += 4;
jap = sgj_new_named_array(jsp, jop,
- "user_data_segment_referral_descriptor");
+ "user_data_segment_referral_descriptor_list");
for (k = 0, f = 1; (k + 4) < dlen; k += g, dp += g, ++f) {
int ntpgd = dp[3];
@@ -1309,7 +1363,8 @@ sgj_uds_referral_descriptor(sgj_state * jsp, sgj_opaque_p jop,
sgj_add_nv_ihex(jsp, jo2p, "first_user_date_sgment_lba", ull);
ull = sg_get_unaligned_be64(dp + 12);
sgj_add_nv_ihex(jsp, jo2p, "last_user_date_sgment_lba", ull);
- ja2p = sgj_new_named_array(jsp, jo2p, "target_port_group_descriptor");
+ ja2p = sgj_new_named_array(jsp, jo2p,
+ "target_port_group_descriptor_list");
for (j = 0; j < ntpgd; ++j) {
jo3p = sgj_new_unattached_object(jsp);
tp = dp + 20 + (j * 4);
@@ -1358,7 +1413,7 @@ sgj_get_sense_descriptors(sgj_state * jsp, sgj_opaque_p jop,
add_sb_len = sshp->additional_length;
add_sb_len = (add_sb_len < sb_len) ? add_sb_len : sb_len;
sense_key = sshp->sense_key;
- jap = sgj_new_named_array(jsp, jop, "sense_data_descriptor");
+ jap = sgj_new_named_array(jsp, jop, "sense_data_descriptor_list");
for (descp = sbp, k = 0; (k < add_sb_len);
k += desc_len, descp += desc_len) {
diff --git a/src/sg_decode_sense.c b/src/sg_decode_sense.c
index 4f503033..83f1d1fa 100644
--- a/src/sg_decode_sense.c
+++ b/src/sg_decode_sense.c
@@ -505,10 +505,10 @@ main(int argc, char *argv[])
} else {
if (as_json) {
sgj_get_sense(jsp, jop, op->sense, op->sense_len);
- if (jsp->pr_output) {
+ if (jsp->pr_out_hr) {
sg_get_sense_str(NULL, op->sense, op->sense_len,
op->verbose, blen, b);
- sgj_pr_str_output(jsp, b, strlen(b));
+ sgj_pr_str_out_hr(jsp, b, strlen(b));
}
} else {
sg_get_sense_str(NULL, op->sense, op->sense_len,
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 3a098774..c9022516 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -8,7 +8,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This program outputs information provided by a SCSI INQUIRY command.
- * It is mainly based on the SCSI SPC-5 document at https://www.t10.org .
+ * It is mainly based on the SCSI SPC-6 document at https://www.t10.org .
*
* Acknowledgment:
* - Martin Schwenke <martin at meltin dot net> added the raw switch and
diff --git a/src/sg_inq_data.c b/src/sg_inq_data.c
index 9458d6b8..f01bc5f0 100644
--- a/src/sg_inq_data.c
+++ b/src/sg_inq_data.c
@@ -34,7 +34,7 @@ const char * sg_ansi_version_arr[16] =
"SPC-2", /* ANSI INCITS 351-2001, ISO/IEC 14776-452 */
"SPC-3", /* ANSI INCITS 408-2005, ISO/IEC 14776-453 */
"SPC-4", /* ANSI INCITS 513-2015 */
- "SPC-5",
+ "SPC-5", /* ANSI INCITS 502-2020 */
"ecma=1, [8h]",
"ecma=1, [9h]",
"ecma=1, [Ah]",
diff --git a/src/sg_opcodes.c b/src/sg_opcodes.c
index 8e29ea30..4d8fe0c7 100644
--- a/src/sg_opcodes.c
+++ b/src/sg_opcodes.c
@@ -1386,7 +1386,7 @@ start_response:
sgj_add_nv_b(jsp, jop, "qaes", rsoc_buff[1] & 0x4);
sgj_add_nv_b(jsp, jop, "qtss", rsoc_buff[1] & 0x2);
sgj_add_nv_b(jsp, jop, "itnrs", rsoc_buff[1] & 0x1);
- if (! jsp->pr_output)
+ if (! jsp->pr_out_hr)
goto fini;
}
sgj_pr_hr(jsp, "\nTask Management Functions supported by device:\n");
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index ff9e9cf1..89c982e4 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -42,7 +42,7 @@
*/
-static const char * version_str = "1.73 20220701"; /* spc6r06 + sbc5r01 */
+static const char * version_str = "1.73 20220705"; /* spc6r06 + sbc5r01 */
#define MY_NAME "sg_decode_sense"
@@ -116,7 +116,7 @@ static int svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
static int svpd_unable_to_decode(int sg_fd, struct opts_t * op, int subvalue,
int off);
-static int decode_dev_ids(const char * print_if_found, int num_leading,
+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);
@@ -198,7 +198,7 @@ static struct svpd_values_name_t standard_vpd_pg[] = {
"protection types (SBC)"},
{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_NOPE_WANT_STD_INQ, 0, -1, "sinq", "Standard inquiry data format"},
{VPD_UNIT_SERIAL_NUM, 0, -1, "sn", "Unit serial number"},
{VPD_SCSI_PORTS, 0, -1, "sp", "SCSI ports"},
{VPD_SECURITY_TOKEN, 0, 0x11, "st", "Security token (OSD)"},
@@ -439,7 +439,7 @@ static const char * sg_ansi_version_arr[16] =
"SPC-2", /* ANSI INCITS 351-2001, ISO/IEC 14776-452 */
"SPC-3", /* ANSI INCITS 408-2005, ISO/IEC 14776-453 */
"SPC-4", /* ANSI INCITS 513-2015 */
- "SPC-5",
+ "SPC-5", /* ANSI INCITS 502-2020 */
"ecma=1, [8h]",
"ecma=1, [9h]",
"ecma=1, [Ah]",
@@ -450,61 +450,186 @@ 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 *
+hot_pluggable_str(int hp)
+{
+ switch (hp) {
+ case 0:
+ return "No information";
+ case 1:
+ return "target device designed to be removed from SCSI domain";
+ case 2:
+ return "target device not designed to be removed from SCSI domain";
+ default:
+ return "value reserved by T10";
+ }
+}
+
+static const char *
+tpgs_str(int tpgs)
+{
+ switch (tpgs) {
+ case 1:
+ return "only implicit asymmetric logical unit access";
+ case 2:
+ return "only explicit asymmetric logical unit access";
+ case 3:
+ return "both explicit and implicit asymmetric logical unit access";
+ case 0:
+ default:
+ return "not supported";
+ }
+}
+
static void
-std_inq_decode(uint8_t * b, int len, int verbose)
+std_inq_decode(uint8_t * b, int len, struct opts_t * op, sgj_opaque_p jop)
{
- int pqual, n;
+ uint8_t ver;
+ int pqual, pdt, hp, tpgs, j, n;
+ sgj_state * jsp = &op->json_st;
+ sgj_opaque_p jo2p;
+ const char * cp;
+ char c[256];
+ static const int clen = sizeof(c);
+ static const char * np = "Standard INQUIRY data format:";
- if (len < 4)
+ if (len < 4) {
+ pr2serr("%s: len [%d] too short\n", __func__, len);
return;
+ }
pqual = (b[0] & 0xe0) >> 5;
- printf("standard INQUIRY:");
+ pdt = b[0] & PDT_MASK;
+ hp = (b[1] >> 4) & 0x3;
+ ver = b[2];
+ sgj_pr_hr(jsp, "%s", np);
if (0 == pqual)
- printf("\n");
- else if (1 == pqual)
- printf(" [PQ indicates LU temporarily unavailable]\n");
- else if (3 == pqual)
- printf(" [PQ indicates LU not accessible via this port]\n");
- else
- printf(" [reserved or vendor specific qualifier [%d]]\n", pqual);
- printf(" PQual=%d PDT=%d RMB=%d LU_CONG=%d hot_pluggable=%d "
- "version=0x%02x ", pqual, b[0] & PDT_MASK, !!(b[1] & 0x80),
- !!(b[1] & 0x40), (b[1] >> 4) & 0x3, (unsigned int)b[2]);
- printf(" [%s]\n", sg_ansi_version_arr[b[2] & 0xf]);
- printf(" [AERC=%d] [TrmTsk=%d] NormACA=%d HiSUP=%d "
+ sgj_pr_hr(jsp, "\n");
+ else {
+ cp = pqual_str(pqual);
+
+ if (pqual < 3)
+ sgj_pr_hr(jsp, " [PQ indicates %s]\n", cp);
+ else
+ sgj_pr_hr(jsp, " [PQ indicates %s [0x%x] ]\n", cp, pqual);
+ }
+ sgj_pr_hr(jsp, " PQual=%d PDT=%d RMB=%d LU_CONG=%d hot_pluggable="
+ "%d version=0x%02x [%s]\n", pqual, pdt, !!(b[1] & 0x80),
+ !!(b[1] & 0x40), hp, ver, sg_ansi_version_arr[ver & 0xf]);
+ sgj_pr_hr(jsp, " [AERC=%d] [TrmTsk=%d] NormACA=%d HiSUP=%d "
" Resp_data_format=%d\n",
!!(b[3] & 0x80), !!(b[3] & 0x40), !!(b[3] & 0x20),
!!(b[3] & 0x10), b[3] & 0x0f);
if (len < 5)
- return;
- n = b[4] + 5;
- if (verbose)
- pr2serr(">> requested %d bytes, %d bytes available\n", len, n);
- printf(" SCCS=%d ACC=%d TPGS=%d 3PC=%d Protect=%d ",
- !!(b[5] & 0x80), !!(b[5] & 0x40), ((b[5] & 0x30) >> 4),
- !!(b[5] & 0x08), !!(b[5] & 0x01));
- printf(" [BQue=%d]\n EncServ=%d ", !!(b[6] & 0x80), !!(b[6] & 0x40));
+ goto skip1;
+ j = b[4] + 5;
+ if (op->verbose > 2)
+ pr2serr(">> requested %d bytes, %d bytes available\n", len, j);
+ sgj_pr_hr(jsp, " SCCS=%d ACC=%d TPGS=%d 3PC=%d Protect=%d "
+ "[BQue=%d]\n", !!(b[5] & 0x80), !!(b[5] & 0x40),
+ ((b[5] & 0x30) >> 4), !!(b[5] & 0x08), !!(b[5] & 0x01),
+ !!(b[6] & 0x80));
+ n = 0;
+ n += sg_scnpr(c + n, clen - n, "EncServ=%d ", !!(b[6] & 0x40));
if (b[6] & 0x10)
- printf("MultiP=1 (VS=%d) ", !!(b[6] & 0x20));
+ n += sg_scnpr(c + n, clen - n, "MultiP=1 (VS=%d) ", !!(b[6] & 0x20));
else
- printf("MultiP=0 ");
- printf("[MChngr=%d] [ACKREQQ=%d] Addr16=%d\n [RelAdr=%d] ",
- !!(b[6] & 0x08), !!(b[6] & 0x04), !!(b[6] & 0x01),
- !!(b[7] & 0x80));
- printf("WBus16=%d Sync=%d [Linked=%d] [TranDis=%d] ",
- !!(b[7] & 0x20), !!(b[7] & 0x10), !!(b[7] & 0x08),
- !!(b[7] & 0x04));
- printf("CmdQue=%d\n", !!(b[7] & 0x02));
+ n += sg_scnpr(c + n, clen - n, "MultiP=0 ");
+ n += sg_scnpr(c + n, clen - n, "[MChngr=%d] [ACKREQQ=%d] Addr16=%d",
+ !!(b[6] & 0x08), !!(b[6] & 0x04), !!(b[6] & 0x01));
+ sgj_pr_hr(jsp, " %s\n", c);
+ sgj_pr_hr(jsp, " [RelAdr=%d] WBus16=%d Sync=%d [Linked=%d] "
+ "[TranDis=%d] CmdQue=%d\n", !!(b[7] & 0x80), !!(b[7] & 0x20),
+ !!(b[7] & 0x10), !!(b[7] & 0x08), !!(b[7] & 0x04),
+ !!(b[7] & 0x02));
+ if (len < 36)
+ goto skip1;
+ sgj_pr_hr(jsp, " Vendor_identification: %.8s\n", b + 8);
+ sgj_pr_hr(jsp, " Product_identification: %.16s\n", b + 16);
+ sgj_pr_hr(jsp, " Product_revision_level: %.4s\n", b + 32);
+skip1:
+ if (! jsp->pr_as_json || (len < 8))
+ return;
+ 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,
+ sg_get_pdt_str(pdt, clen, c));
+ sgj_add_nv_ihex_ane(jsp, jo2p, "rmb", !!(b[1] & 0x80), false,
+ "Removable Medium Bit");
+ sgj_add_nv_ihex_ane(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,
+ "Asynchronous Event Reporting Capability (obsolete "
+ "SPC-3)");
+ sgj_add_nv_ihex_ane(jsp, jo2p, "trmtsk", !!(b[3] & 0x40), false,
+ "Terminate Task (obsolete SPC-2)");
+ sgj_add_nv_ihex_ane(jsp, jo2p, "normaca", !!(b[3] & 0x20), false,
+ "Normal ACA (Auto Contingent Allegiance)");
+ sgj_add_nv_ihex_ane(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,
+ "SCC (SCSI Storage Commands) Supported");
+ sgj_add_nv_ihex_ane(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,
+ tpgs_str(tpgs), "Target Port Group Support");
+ sgj_add_nv_ihex_ane(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,
+ "Basic task management model (obsolete SPC-4)");
+ sgj_add_nv_ihex_ane(jsp, jo2p, "encserv", !!(b[6] & 0x40), false,
+ "Enclousure Services supported");
+ sgj_add_nv_ihex_ane(jsp, jo2p, "multip", !!(b[6] & 0x10), false,
+ "Multiple SCSI port");
+ sgj_add_nv_ihex_ane(jsp, jo2p, "mchngr", !!(b[6] & 0x8), false,
+ "Medium changer (obsolete SPC-4)");
+ sgj_add_nv_ihex_ane(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,
+ "Linked Commands (obsolete in SPC-4)");
+ sgj_add_nv_ihex_ane(jsp, jo2p, "cmdque", !!(b[7] & 0x2), false,
+ "Command Management Model (command queuing)");
+ if (len < 16)
+ return;
+ snprintf(c, clen, "%.8s", b + 8);
+ sgj_add_nv_s(jsp, jo2p, "t10_vendor_identification", c);
+ if (len < 32)
+ return;
+ snprintf(c, clen, "%.16s", b + 16);
+ sgj_add_nv_s(jsp, jo2p, "product_identification", c);
if (len < 36)
return;
- printf(" Vendor_identification: %.8s\n", b + 8);
- printf(" Product_identification: %.16s\n", b + 16);
- printf(" Product_revision_level: %.4s\n", b + 32);
+ snprintf(c, clen, "%.4s", b + 32);
+ sgj_add_nv_s(jsp, jo2p, "product_revision_level", c);
}
static void
-decode_id_vpd_variants(uint8_t * buff, int len, int subvalue,
- struct opts_t * op, sgj_opaque_p jop)
+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;
uint8_t * b;
@@ -519,24 +644,24 @@ decode_id_vpd_variants(uint8_t * buff, int len, int subvalue,
m_d = -1;
m_cs = -1;
if (0 == subvalue) {
- decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_LU), 0, b, blen,
- VPD_ASSOC_LU, m_d, m_cs, op, jop);
- decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TPORT), 0, b, blen,
- VPD_ASSOC_TPORT, m_d, m_cs, op, jop);
- decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TDEVICE), 0, b, blen,
- VPD_ASSOC_TDEVICE, m_d, m_cs, op, jop);
+ filter_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_LU), 0, b, blen,
+ VPD_ASSOC_LU, m_d, m_cs, 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);
+ filter_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TDEVICE), 0, b, blen,
+ VPD_ASSOC_TDEVICE, m_d, m_cs, op, jap);
} else if (VPD_DI_SEL_AS_IS == subvalue)
- decode_dev_ids(NULL, 0, b, blen, m_a, m_d, m_cs, op, jop);
+ filter_dev_ids(NULL, 0, b, blen, m_a, m_d, m_cs, op, jap);
else {
if (VPD_DI_SEL_LU & subvalue)
- decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_LU), 0, b, blen,
- VPD_ASSOC_LU, m_d, m_cs, op, jop);
+ filter_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_LU), 0, b, blen,
+ VPD_ASSOC_LU, m_d, m_cs, op, jap);
if (VPD_DI_SEL_TPORT & subvalue)
- decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TPORT), 0, b,
- blen, VPD_ASSOC_TPORT, m_d, m_cs, op, jop);
+ filter_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TPORT), 0, b,
+ blen, VPD_ASSOC_TPORT, m_d, m_cs, op, jap);
if (VPD_DI_SEL_TARGET & subvalue)
- decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TDEVICE), 0,
- b, blen, VPD_ASSOC_TDEVICE, m_d, m_cs, op, jop);
+ filter_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TDEVICE), 0,
+ b, blen, VPD_ASSOC_TDEVICE, m_d, m_cs, op, jap);
}
}
@@ -561,13 +686,18 @@ static const char * network_service_type_arr[] =
/* VPD_MAN_NET_ADDR */
static void
-decode_net_man_vpd(uint8_t * buff, int len, int do_hex)
+decode_net_man_vpd(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap)
{
- int k, bump, na_len;
+ 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 == do_hex) || (do_hex > 2)) {
- hex2stdout(buff, len, (1 == do_hex) ? 0 : -1);
+ if ((1 == op->do_hex) || (op->do_hex > 2)) {
+ hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
return;
}
if (len < 4) {
@@ -578,22 +708,34 @@ decode_net_man_vpd(uint8_t * buff, int len, int do_hex)
len -= 4;
bp = buff + 4;
for (k = 0; k < len; k += bump, bp += bump) {
- printf(" %s, Service type: %s\n",
- sg_get_desig_assoc_str((bp[0] >> 5) & 0x3),
- network_service_type_arr[bp[0] & 0x1f]);
+ 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);
- 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 (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 (do_hex > 1) {
+ if (op->do_hex > 1) {
printf(" Network address:\n");
hex2stdout((bp + 4), na_len, 0);
} else
- printf(" %s\n", bp + 4);
+ 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;
}
}
}
@@ -650,9 +792,12 @@ decode_mode_policy_vpd(uint8_t * buff, int len, int do_hex)
/* VPD_SCSI_PORTS */
static void
decode_scsi_ports_vpd(uint8_t * buff, int len, struct opts_t * op,
- sgj_opaque_p jop)
+ sgj_opaque_p jap)
{
int k, bump, rel_port, ip_tid_len, tpd_len;
+ sgj_state * jsp = &op->json_st;
+ sgj_opaque_p jo2p = NULL;
+ sgj_opaque_p ja2p = NULL;
uint8_t * bp;
if ((1 == op->do_hex) || (op->do_hex > 2)) {
@@ -667,7 +812,9 @@ decode_scsi_ports_vpd(uint8_t * buff, int len, struct opts_t * op,
bp = buff + 4;
for (k = 0; k < len; k += bump, bp += bump) {
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);
+ jo2p = sgj_new_unattached_object(jsp);
+ 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) {
@@ -677,13 +824,14 @@ decode_scsi_ports_vpd(uint8_t * buff, int len, struct opts_t * op,
}
if (ip_tid_len > 0) {
if (op->do_hex > 1) {
- printf(" Initiator port transport id:\n");
+ sgj_pr_hr(jsp, " Initiator port transport id:\n");
hex2stdout((bp + 8), ip_tid_len, 1);
} else {
char b[1024];
- printf("%s", sg_decode_transportid_str(" ", bp + 8,
- ip_tid_len, true, sizeof(b), 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);
@@ -694,23 +842,31 @@ decode_scsi_ports_vpd(uint8_t * buff, int len, struct opts_t * op,
}
if (tpd_len > 0) {
if (op->do_hex > 1) {
- printf(" Target port descriptor(s):\n");
+ sgj_pr_hr(jsp, " Target port descriptor(s):\n");
hex2stdout(bp + bump + 4, tpd_len, 1);
} else {
if ((0 == op->do_quiet) || (ip_tid_len > 0))
- printf(" Target port descriptor(s):\n");
- decode_dev_ids("", 2 /* leading spaces */, bp + bump + 4,
- tpd_len, VPD_ASSOC_TPORT, -1, -1, op, jop);
+ sgj_pr_hr(jsp, " Target port descriptor(s):\n");
+ if (jsp->pr_as_json) {
+ sgj_opaque_p jo3p = sgj_new_named_object(jsp, jo2p,
+ "target_port");
+
+ ja2p = sgj_new_named_array(jsp, jo3p,
+ "designation_descriptor_list");
+ }
+ filter_dev_ids("", 2 /* leading spaces */, bp + bump + 4,
+ tpd_len, VPD_ASSOC_TPORT, -1, -1, op, ja2p);
}
}
bump += tpd_len + 4;
+ sgj_add_nv_o(jsp, jap, NULL, jo2p);
}
}
/* Prints outs an abridged set of device identification designators
selected by association, designator type and/or code set. */
static int
-decode_dev_ids_quiet(uint8_t * buff, int len, int m_assoc,
+filter_dev_ids_quiet(uint8_t * buff, int len, int m_assoc,
int m_desig_type, int m_code_set)
{
int k, m, p_id, c_set, piv, desig_type, i_len, naa, off, u;
@@ -904,14 +1060,14 @@ decode_dev_ids_quiet(uint8_t * buff, int len, int m_assoc,
return 0;
}
-/* Prints outs designation descriptors (dd_s)selected by association,
+/* Prints outs designation descriptors (dd_s) selected by association,
designator type and/or code set. */
static int
-decode_dev_ids(const char * print_if_found, int num_leading, uint8_t * buff,
+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)
+ struct opts_t * op, sgj_opaque_p jap)
{
- bool printed, sgj_output;
+ bool printed, sgj_out_hr;
int assoc, off, u, i_len;
const uint8_t * bp;
sgj_state * jsp = &op->json_st;
@@ -920,7 +1076,7 @@ decode_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 decode_dev_ids_quiet(buff, len, m_assoc, m_desig_type,
+ return filter_dev_ids_quiet(buff, len, m_assoc, m_desig_type,
m_code_set);
if (num_leading > (int)(sizeof(sp) - 2))
num_leading = sizeof(sp) - 2;
@@ -946,14 +1102,15 @@ decode_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_output = false;
+ sgj_out_hr = false;
if (jsp->pr_as_json) {
- sgj_opaque_p jo2p =
- sgj_new_named_object(jsp, jop, "designation_descriptor");
+ sgj_opaque_p jo2p;
+ jo2p = sgj_new_unattached_object(jsp);
sgj_get_designation_descriptor(jsp, jo2p, bp, i_len + 4);
- if (jsp->pr_output)
- sgj_output = true;
+ sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p);
+ if (jsp->pr_out_hr)
+ sgj_out_hr = true;
else
continue;
}
@@ -962,23 +1119,23 @@ decode_dev_ids(const char * print_if_found, int num_leading, uint8_t * buff,
printed = true;
if (strlen(print_if_found) > 0) {
snprintf(b, blen, " %s:", print_if_found);
- if (sgj_output)
- sgj_pr_str_output(jsp, b, strlen(b));
+ if (sgj_out_hr)
+ sgj_pr_str_out_hr(jsp, b, strlen(b));
else
printf("%s\n", b);
}
}
if (NULL == print_if_found) {
snprintf(b, blen, " %s%s:", sp, sg_get_desig_assoc_str(assoc));
- if (sgj_output)
- sgj_pr_str_output(jsp, b, strlen(b));
+ if (sgj_out_hr)
+ sgj_pr_str_out_hr(jsp, b, strlen(b));
else
printf("%s\n", b);
}
sg_get_designation_descriptor_str(sp, bp, i_len + 4, false,
op->do_long, blen, b);
- if (sgj_output)
- sgj_pr_str_output(jsp, b, strlen(b));
+ if (sgj_out_hr)
+ sgj_pr_str_out_hr(jsp, b, strlen(b));
else
printf("%s", b);
}
@@ -1132,17 +1289,28 @@ decode_x_inq_vpd(uint8_t * b, int len, int do_hex, bool do_long,
/* VPD_SOFTW_INF_ID */
static void
-decode_softw_inf_id(uint8_t * buff, int len, int do_hex)
+decode_softw_inf_id(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jap)
{
- if (do_hex) {
- hex2stdout(buff, len, (1 == do_hex) ? 0 : -1);
+ 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)
- printf(" IEEE identifier: 0x%" PRIx64 "\n",
- sg_get_unaligned_be48(buff + 0));
+ 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 */
@@ -1263,8 +1431,8 @@ decode_dev_constit_vpd(const uint8_t * buff, int len, struct opts_t * op,
int k, j, res, bump, csd_len;
uint16_t constit_type;
const uint8_t * bp;
- const char * dcp = "Device constituents VPD page";
char b[64];
+ static const char * dcp = "Device constituents VPD page";
if ((1 == op->do_hex) || (op->do_hex > 2)) {
hex2stdout(buff, len, (1 == op->do_hex) ? 0 : -1);
@@ -1365,7 +1533,7 @@ decode_power_consumption_vpd(uint8_t * buff, int len, int do_hex)
int k, bump;
uint8_t * bp;
unsigned int value;
- const char * pcp = "Power consumption VPD page";
+ static const char * pcp = "Power consumption VPD page";
if ((1 == do_hex) || (do_hex > 2)) {
hex2stdout(buff, len, (1 == do_hex) ? 1 : -1);
@@ -2817,15 +2985,22 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
bool allow_name, allow_if_found, long_notquiet, qt;
bool vpd_supported = false;
bool inhex_active = (-1 == sg_fd);
- int len, pdt, num, k, resid, alloc_len, pn, vb;
+ int len, pdt, pqual, num, k, resid, alloc_len, pn, vb;
int res = 0;
const struct svpd_values_name_t * vnp;
sgj_state * jsp = &op->json_st;
uint8_t * rp;
+ sgj_opaque_p jap = NULL;
+ sgj_opaque_p jo2p = NULL;
const char * np;
const char * pre = (prefix ? prefix : "");;
+ const char * pdt_str;
+ bool as_json = jsp->pr_as_json;
+ bool not_json = ! as_json;
char obuff[DEF_ALLOC_LEN];
- char b[48];
+ char b[120];
+ char d[48];
+ static const int blen = sizeof(b);
vb = op->verbose;
qt = op->do_quiet;
@@ -2868,6 +3043,10 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return sg_convert_errno(EDOM);
}
}
+ pdt = rp[0] & PDT_MASK;
+ pdt_str = sg_get_pdt_str(pdt, sizeof(d), d);
+ pqual = (rp[0] & 0xe0) >> 5;
+
switch(pn) {
case VPD_NOPE_WANT_STD_INQ: /* -2 (want standard inquiry response) */
if (!inhex_active) {
@@ -2890,55 +3069,79 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
dStrRaw(rp, alloc_len);
else if (op->do_hex) {
if (! op->do_quiet && (op->do_hex < 3))
- printf("Standard Inquiry response:\n");
+ sgj_pr_hr(jsp, "Standard Inquiry data format:\n");
hex2stdout(rp, alloc_len, (1 == op->do_hex) ? 0 : -1);
} else
- std_inq_decode(rp, alloc_len, vb);
+ std_inq_decode(rp, alloc_len, op, jop);
return 0;
}
break;
case VPD_SUPPORTED_VPDS: /* 0x0 */
np = "Supported VPD pages 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 (op->do_hex)
hex2stdout(rp, len, (1 == op->do_hex) ? 0 : -1);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
- printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
+ "%s]\n", pqual, pdt_str);
num = rp[3];
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);
+ jap = sgj_new_named_array(jsp, jo2p,
+ "supported_vpd_page_list");
+ }
for (k = 0; k < num; ++k) {
pn = rp[4 + k];
+ snprintf(b, blen, "0x%02x", pn);
vnp = sdp_get_vpd_detail(pn, -1, pdt);
if (vnp) {
if (op->do_long)
- printf(" 0x%02x %s [%s]\n", pn, vnp->name,
- vnp->acron);
+ sgj_pr_hr(jsp, " %s %s [%s]\n", b,
+ vnp->name, vnp->acron);
else
- printf(" %s [%s]\n", vnp->name, vnp->acron);
+ sgj_pr_hr(jsp, " %s [%s]\n", vnp->name,
+ vnp->acron);
} else if (op->vend_prod_num >= 0) {
vnp = svpd_find_vendor_by_num(pn, op->vend_prod_num);
if (vnp) {
if (op->do_long)
- printf(" 0x%02x %s [%s]\n", pn, vnp->name,
- vnp->acron);
+ sgj_pr_hr(jsp, " %s %s [%s]\n", b,
+ vnp->name, vnp->acron);
else
- printf(" %s [%s]\n", vnp->name, vnp->acron);
+ sgj_pr_hr(jsp, " %s [%s]\n", vnp->name,
+ vnp->acron);
} else
- printf(" 0x%x\n", pn);
+ sgj_pr_hr(jsp, " %s\n", b);
} else
- printf(" 0x%x\n", pn);
+ sgj_pr_hr(jsp, " %s\n", b);
+ if (as_json) {
+ jo2p = sgj_new_unattached_object(jsp);
+ sgj_add_nv_i(jsp, jo2p, "i", pn);
+ sgj_add_nv_s(jsp, jo2p, "hex", b + 2);
+ if (vnp) {
+ sgj_add_nv_s(jsp, jo2p, "name", vnp->name);
+ sgj_add_nv_s(jsp, jo2p, "acronym", vnp->acron);
+ } else {
+ sgj_add_nv_s(jsp, jo2p, "name", "unknown");
+ sgj_add_nv_s(jsp, jo2p, "acronym", "unknown");
+ }
+ sgj_add_nv_o(jsp, jap, NULL /* name */, jo2p);
+ }
}
}
return 0;
@@ -2946,28 +3149,33 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
break;
case VPD_UNIT_SERIAL_NUM: /* 0x80 */
np = "Unit serial number VPD page:";
- if (allow_name)
- printf("%s%s\n", pre, np);
+ if (allow_name && not_json)
+ 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 (op->do_hex)
hex2stdout(rp, len, (1 == op->do_hex) ? 0 : -1);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
- printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
+ "%s]\n", pqual, pdt_str);
memset(obuff, 0, sizeof(obuff));
len -= 4;
if (len >= (int)sizeof(obuff))
len = sizeof(obuff) - 1;
memcpy(obuff, rp + 4, len);
- printf(" Unit serial number: %s\n", obuff);
+ 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);
}
return 0;
}
@@ -2985,12 +3193,20 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
else if (op->do_hex)
hex2stdout(rp, len, (1 == op->do_hex) ? 0 : -1);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
sgj_pr_hr(jsp, " [PQual=%d Peripheral device type: "
- "%s]\n", (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
- decode_id_vpd_variants(rp, len, subvalue, op, jop);
+ "%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);
+ jap = sgj_new_named_array(jsp, jo2p,
+ "designation_descriptor_list");
+ }
+ device_id_vpd_variants(rp, len, subvalue, op, jap);
}
return 0;
}
@@ -2998,20 +3214,28 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case VPD_SOFTW_INF_ID: /* 0x84 */
np = "Software interface identification 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 {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
- printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
- decode_softw_inf_id(rp, len, op->do_hex);
+ 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);
+ jap = sgj_new_named_array(jsp, jo2p,
+ "software_interface_identifier_list");
+ }
+ decode_softw_inf_id(rp, len, op, jap);
}
return 0;
}
@@ -3019,15 +3243,26 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case VPD_MAN_NET_ADDR: /* 0x85 */
np= "Management network addresses 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
- decode_net_man_vpd(rp, len, op->do_hex);
+ 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);
+ jap = sgj_new_named_array(jsp, jo2p,
+ "network_services_descriptor_list");
+ }
+ decode_net_man_vpd(rp, len, op, jap);
+ }
return 0;
}
break;
@@ -3054,11 +3289,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
} else
protect = !!(sir.byte_5 & 0x1); /* SPC-3 and later */
}
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_x_inq_vpd(rp, len, op->do_hex, long_notquiet, protect);
}
return 0;
@@ -3075,11 +3308,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_mode_policy_vpd(rp, len, op->do_hex);
}
return 0;
@@ -3088,20 +3319,28 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case VPD_SCSI_PORTS: /* 0x88 */
np = "SCSI Ports 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 {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
- printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
- decode_scsi_ports_vpd(rp, len, op, 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);
+ jap = sgj_new_named_array(jsp, jo2p,
+ "scsi_port_descriptor_list");
+ }
+ decode_scsi_ports_vpd(rp, len, op, jap);
}
return 0;
}
@@ -3126,11 +3365,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
else if (op->do_raw)
dStrRaw(rp, len);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_ata_info_vpd(rp, len, long_notquiet, op->do_hex);
}
return 0;
@@ -3147,11 +3384,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_power_condition(rp, len, op->do_hex);
}
return 0;
@@ -3183,11 +3418,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_power_consumption_vpd(rp, len, op->do_hex);
}
return 0;
@@ -3206,11 +3439,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
else if (1 == op->do_hex)
hex2stdout(rp, len, 0);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_3party_copy_vpd(rp, len, op->do_hex, pdt, vb);
}
return 0;
@@ -3227,11 +3458,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else {
- pdt = rsp_buff[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_proto_lu_vpd(rp, len, op->do_hex);
}
return 0;
@@ -3248,11 +3477,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_proto_port_vpd(rp, len, op->do_hex);
}
return 0;
@@ -3269,11 +3496,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_feature_sets_vpd(rp, len, op);
}
return 0;
@@ -3282,7 +3507,6 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case 0xb0: /* depends on pdt */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
- pdt = rp[0] & PDT_MASK;
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
np = "Block limits VPD page (SBC):";
@@ -3304,11 +3528,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_b0_vpd(rp, len, op->do_hex, pdt);
}
return 0;
@@ -3319,7 +3541,6 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case 0xb1: /* depends on pdt */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
- pdt = rp[0] & PDT_MASK;
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
np = "Block device characteristics VPD page (SBC):";
@@ -3346,8 +3567,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
else {
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_b1_vpd(rp, len, op->do_hex, pdt);
}
return 0;
@@ -3358,7 +3578,6 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case 0xb2: /* VPD page depends on pdt */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
- pdt = rp[0] & PDT_MASK;
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
np = "Logical block provisioning VPD page (SBC):";
@@ -3379,8 +3598,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
else {
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_b2_vpd(rp, len, pdt, op);
}
return 0;
@@ -3412,8 +3630,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
else {
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_b3_vpd(rp, len, op->do_hex, pdt);
}
return 0;
@@ -3424,7 +3641,6 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case 0xb4: /* VPD page depends on pdt */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
- pdt = rp[0] & PDT_MASK;
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
np = "Supported block lengths and protection types VPD page "
@@ -3446,8 +3662,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
else {
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_b4_vpd(rp, len, op->do_hex, pdt);
}
return 0;
@@ -3458,7 +3673,6 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case 0xb5: /* VPD page depends on pdt */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
- pdt = rp[0] & PDT_MASK;
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
np = "Block device characteristics extension VPD page (SBC):";
@@ -3479,8 +3693,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
else {
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_b5_vpd(rp, len, op->do_hex, pdt);
}
return 0;
@@ -3491,7 +3704,6 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case VPD_ZBC_DEV_CHARS: /* 0xb6 for both pdt=0 and pdt=0x14 */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
- pdt = rp[0] & PDT_MASK;
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
np = "Zoned block device characteristics VPD page (SBC, "
@@ -3510,8 +3722,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
else {
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_zbdch_vpd(rp, len, op->do_hex);
}
return 0;
@@ -3522,7 +3733,6 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case 0xb7:
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
- pdt = rp[0] & PDT_MASK;
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
np = "Block limits extension VPD page (SBC):";
@@ -3538,11 +3748,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_b7_vpd(rp, len, op->do_hex, pdt);
}
return 0;
@@ -3553,7 +3761,6 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case 0xb8: /* VPD_FORMAT_PRESETS */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
- pdt = rp[0] & PDT_MASK;
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
np = "Format presets VPD page (SBC):";
@@ -3569,11 +3776,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_format_presets_vpd(rp, len, op->do_hex);
}
return 0;
@@ -3584,7 +3789,6 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
case 0xb9: /* VPD_CON_POS_RANGE */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
- pdt = rp[0] & PDT_MASK;
switch (pdt) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_ZBC:
np = "Concurrent positioning ranges VPD page (SBC):";
@@ -3600,11 +3804,9 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->do_raw)
dStrRaw(rp, len);
else {
- pdt = rp[0] & PDT_MASK;
if (vb || long_notquiet)
printf(" [PQual=%d Peripheral device type: %s]\n",
- (rp[0] & 0xe0) >> 5,
- sg_get_pdt_str(pdt, sizeof(b), b));
+ pqual, pdt_str);
decode_con_pos_range_vpd(rp, len, op->do_hex);
}
return 0;
@@ -3689,6 +3891,9 @@ svpd_decode_all(int sg_fd, struct opts_t * op, sgj_opaque_p jop)
int prev_pn = -1;
res = 0;
+ if (op->page_given && (VPD_NOPE_WANT_STD_INQ == op->vpd_pn))
+ return svpd_decode_t10(-1, op, jop, 0, 0, NULL);
+
for (k = 0, off = 0; off < in_len; ++k, off += bump) {
rp = rsp_buff + off;
pn = rp[1];
@@ -3698,6 +3903,8 @@ svpd_decode_all(int sg_fd, struct opts_t * op, sgj_opaque_p jop)
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);
@@ -3875,6 +4082,7 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
} else
op->page_str = optarg;
+ op->page_given = true;
break;
case 'q':
op->do_quiet = true;
@@ -3987,19 +4195,22 @@ main(int argc, char * argv[])
jop = sgj_start(MY_NAME, version_str, argc, argv, jsp);
if (op->page_str) {
- if ((0 == strcmp("-1", op->page_str)) ||
- (0 == strcmp("-2", op->page_str)))
+ if ('-' == op->page_str[0])
op->vpd_pn = VPD_NOPE_WANT_STD_INQ;
else if (isalpha((uint8_t)op->page_str[0])) {
vnp = sdp_find_vpd_by_acron(op->page_str);
if (NULL == vnp) {
vnp = svpd_find_vendor_by_acron(op->page_str);
if (NULL == vnp) {
- pr2serr("abbreviation doesn't match a VPD page\n");
- printf("Available standard VPD pages:\n");
- enumerate_vpds(1, 1);
- ret = SG_LIB_SYNTAX_ERROR;
- goto fini;
+ if (0 == strcmp("stdinq", op->page_str)) {
+ vnp = sdp_find_vpd_by_acron("sinq");
+ } else {
+ pr2serr("abbreviation doesn't match a VPD page\n");
+ printf("Available standard VPD pages:\n");
+ enumerate_vpds(1, 1);
+ ret = SG_LIB_SYNTAX_ERROR;
+ goto fini;
+ }
}
}
op->vpd_pn = vnp->value;
@@ -4146,7 +4357,7 @@ main(int argc, char * argv[])
if (op->inhex_fn) {
if ((0 == op->maxlen) || (inhex_len < op->maxlen))
op->maxlen = inhex_len;
- if (op->do_all)
+ if (op->do_all || op->page_given)
res = svpd_decode_all(-1, op, jop);
else {
res = svpd_decode_t10(-1, op, jop, subvalue, 0, NULL);
diff --git a/src/sg_vpd.h b/src/sg_vpd.h
index 67205717..f01ef122 100644
--- a/src/sg_vpd.h
+++ b/src/sg_vpd.h
@@ -32,6 +32,7 @@ struct opts_t {
bool do_force;
bool do_long;
bool do_quiet;
+ bool page_given;
bool verbose_given;
bool version_given;
int do_hex;
diff --git a/testing/tst_sg_lib.c b/testing/tst_sg_lib.c
index 51c109ee..2f44d2fe 100644
--- a/testing/tst_sg_lib.c
+++ b/testing/tst_sg_lib.c
@@ -367,10 +367,10 @@ main(int argc, char * argv[])
}
#if 1
if (as_json) {
- sgj_pr_str_output(jsp, "sg_get_sense_str(ds_data1)", 999);
+ sgj_pr_str_out_hr(jsp, "sg_get_sense_str(ds_data1)", 999);
sg_get_sense_str(leadin, desc_sense_data1,
sizeof(desc_sense_data1), vb, b_len, b);
- sgj_pr_str_output(jsp, b, strlen(b));
+ sgj_pr_str_out_hr(jsp, b, strlen(b));
} else {
printf("sg_get_sense_str(ds_data1):\n");