xref: /aosp_15_r20/external/sg3_utils/src/sg_get_config.c (revision 44704f698541f6367e81f991ef8bb54ccbf3fc18)
1*44704f69SBart Van Assche /*
2*44704f69SBart Van Assche  * Copyright (c) 2004-2018 Douglas Gilbert.
3*44704f69SBart Van Assche  * All rights reserved.
4*44704f69SBart Van Assche  * Use of this source code is governed by a BSD-style
5*44704f69SBart Van Assche  * license that can be found in the BSD_LICENSE file.
6*44704f69SBart Van Assche  *
7*44704f69SBart Van Assche  * SPDX-License-Identifier: BSD-2-Clause
8*44704f69SBart Van Assche  */
9*44704f69SBart Van Assche 
10*44704f69SBart Van Assche #include <unistd.h>
11*44704f69SBart Van Assche #include <fcntl.h>
12*44704f69SBart Van Assche #include <stdio.h>
13*44704f69SBart Van Assche #include <stdlib.h>
14*44704f69SBart Van Assche #include <stdarg.h>
15*44704f69SBart Van Assche #include <stdbool.h>
16*44704f69SBart Van Assche #include <string.h>
17*44704f69SBart Van Assche #include <ctype.h>
18*44704f69SBart Van Assche #include <getopt.h>
19*44704f69SBart Van Assche 
20*44704f69SBart Van Assche #ifdef HAVE_CONFIG_H
21*44704f69SBart Van Assche #include "config.h"
22*44704f69SBart Van Assche #endif
23*44704f69SBart Van Assche #include "sg_lib.h"
24*44704f69SBart Van Assche #include "sg_cmds_basic.h"
25*44704f69SBart Van Assche #include "sg_cmds_mmc.h"
26*44704f69SBart Van Assche #include "sg_unaligned.h"
27*44704f69SBart Van Assche #include "sg_pr2serr.h"
28*44704f69SBart Van Assche 
29*44704f69SBart Van Assche /* A utility program originally written for the Linux OS SCSI subsystem.
30*44704f69SBart Van Assche  *
31*44704f69SBart Van Assche  * This program outputs information provided by a SCSI "Get Configuration"
32*44704f69SBart Van Assche    command [0x46] which is only defined for CD/DVDs (in MMC-2,3,4,5,6).
33*44704f69SBart Van Assche 
34*44704f69SBart Van Assche */
35*44704f69SBart Van Assche 
36*44704f69SBart Van Assche static const char * version_str = "0.49 20180626";    /* mmc6r02 */
37*44704f69SBart Van Assche 
38*44704f69SBart Van Assche #define MX_ALLOC_LEN 8192
39*44704f69SBart Van Assche #define NAME_BUFF_SZ 64
40*44704f69SBart Van Assche 
41*44704f69SBart Van Assche #define ME "sg_get_config: "
42*44704f69SBart Van Assche 
43*44704f69SBart Van Assche 
44*44704f69SBart Van Assche static uint8_t resp_buffer[MX_ALLOC_LEN];
45*44704f69SBart Van Assche 
46*44704f69SBart Van Assche static struct option long_options[] = {
47*44704f69SBart Van Assche         {"brief", no_argument, 0, 'b'},
48*44704f69SBart Van Assche         {"current", no_argument, 0, 'c'},
49*44704f69SBart Van Assche         {"help", no_argument, 0, 'h'},
50*44704f69SBart Van Assche         {"hex", no_argument, 0, 'H'},
51*44704f69SBart Van Assche         {"inner-hex", no_argument, 0, 'i'},
52*44704f69SBart Van Assche         {"list", no_argument, 0, 'l'},
53*44704f69SBart Van Assche         {"raw", no_argument, 0, 'R'},
54*44704f69SBart Van Assche         {"readonly", no_argument, 0, 'q'},
55*44704f69SBart Van Assche         {"rt", required_argument, 0, 'r'},
56*44704f69SBart Van Assche         {"starting", required_argument, 0, 's'},
57*44704f69SBart Van Assche         {"verbose", no_argument, 0, 'v'},
58*44704f69SBart Van Assche         {"version", no_argument, 0, 'V'},
59*44704f69SBart Van Assche         {0, 0, 0, 0},
60*44704f69SBart Van Assche };
61*44704f69SBart Van Assche 
62*44704f69SBart Van Assche 
63*44704f69SBart Van Assche static void
usage()64*44704f69SBart Van Assche usage()
65*44704f69SBart Van Assche {
66*44704f69SBart Van Assche     pr2serr("Usage:  sg_get_config [--brief] [--current] [--help] [--hex] "
67*44704f69SBart Van Assche             "[--inner-hex]\n"
68*44704f69SBart Van Assche             "                      [--list] [--raw] [--readonly] [--rt=RT]\n"
69*44704f69SBart Van Assche             "                      [--starting=FC] [--verbose] [--version] "
70*44704f69SBart Van Assche             "DEVICE\n"
71*44704f69SBart Van Assche             "  where:\n"
72*44704f69SBart Van Assche             "    --brief|-b       only give feature names of DEVICE "
73*44704f69SBart Van Assche             "(don't decode)\n"
74*44704f69SBart Van Assche             "    --current|-c     equivalent to '--rt=1' (show "
75*44704f69SBart Van Assche             "current)\n"
76*44704f69SBart Van Assche             "    --help|-h        print usage message then exit\n"
77*44704f69SBart Van Assche             "    --hex|-H         output response in hex\n"
78*44704f69SBart Van Assche             "    --inner-hex|-i    decode to feature name, then output "
79*44704f69SBart Van Assche             "features in hex\n"
80*44704f69SBart Van Assche             "    --list|-l        list all known features + profiles "
81*44704f69SBart Van Assche             "(ignore DEVICE)\n"
82*44704f69SBart Van Assche             "    --raw|-R         output in binary (to stdout)\n"
83*44704f69SBart Van Assche             "    --readonly|-q    open DEVICE read-only (def: open it "
84*44704f69SBart Van Assche             "read-write)\n"
85*44704f69SBart Van Assche             "    --rt=RT|-r RT    default value is 0\n"
86*44704f69SBart Van Assche             "                     0 -> all feature descriptors (regardless "
87*44704f69SBart Van Assche             "of currency)\n"
88*44704f69SBart Van Assche             "                     1 -> all current feature descriptors\n"
89*44704f69SBart Van Assche             "                     2 -> only feature descriptor matching "
90*44704f69SBart Van Assche             "'starting'\n"
91*44704f69SBart Van Assche             "    --starting=FC|-s FC    starting from feature "
92*44704f69SBart Van Assche             "code (FC) value\n"
93*44704f69SBart Van Assche             "    --verbose|-v     verbose\n"
94*44704f69SBart Van Assche             "    --version|-V     output version string\n\n"
95*44704f69SBart Van Assche             "Get configuration information for MMC drive and/or media\n");
96*44704f69SBart Van Assche }
97*44704f69SBart Van Assche 
98*44704f69SBart Van Assche struct val_desc_t {
99*44704f69SBart Van Assche         int val;
100*44704f69SBart Van Assche         const char * desc;
101*44704f69SBart Van Assche };
102*44704f69SBart Van Assche 
103*44704f69SBart Van Assche static struct val_desc_t profile_desc_arr[] = {
104*44704f69SBart Van Assche         {0x0, "No current profile"},
105*44704f69SBart Van Assche         {0x1, "Non-removable disk (obs)"},
106*44704f69SBart Van Assche         {0x2, "Removable disk"},
107*44704f69SBart Van Assche         {0x3, "Magneto optical erasable"},
108*44704f69SBart Van Assche         {0x4, "Optical write once"},
109*44704f69SBart Van Assche         {0x5, "AS-MO"},
110*44704f69SBart Van Assche         {0x8, "CD-ROM"},
111*44704f69SBart Van Assche         {0x9, "CD-R"},
112*44704f69SBart Van Assche         {0xa, "CD-RW"},
113*44704f69SBart Van Assche         {0x10, "DVD-ROM"},
114*44704f69SBart Van Assche         {0x11, "DVD-R sequential recording"},
115*44704f69SBart Van Assche         {0x12, "DVD-RAM"},
116*44704f69SBart Van Assche         {0x13, "DVD-RW restricted overwrite"},
117*44704f69SBart Van Assche         {0x14, "DVD-RW sequential recording"},
118*44704f69SBart Van Assche         {0x15, "DVD-R dual layer sequental recording"},
119*44704f69SBart Van Assche         {0x16, "DVD-R dual layer jump recording"},
120*44704f69SBart Van Assche         {0x17, "DVD-RW dual layer"},
121*44704f69SBart Van Assche         {0x18, "DVD-Download disc recording"},
122*44704f69SBart Van Assche         {0x1a, "DVD+RW"},
123*44704f69SBart Van Assche         {0x1b, "DVD+R"},
124*44704f69SBart Van Assche         {0x20, "DDCD-ROM"},
125*44704f69SBart Van Assche         {0x21, "DDCD-R"},
126*44704f69SBart Van Assche         {0x22, "DDCD-RW"},
127*44704f69SBart Van Assche         {0x2a, "DVD+RW dual layer"},
128*44704f69SBart Van Assche         {0x2b, "DVD+R dual layer"},
129*44704f69SBart Van Assche         {0x40, "BD-ROM"},
130*44704f69SBart Van Assche         {0x41, "BD-R SRM"},
131*44704f69SBart Van Assche         {0x42, "BD-R RRM"},
132*44704f69SBart Van Assche         {0x43, "BD-RE"},
133*44704f69SBart Van Assche         {0x50, "HD DVD-ROM"},
134*44704f69SBart Van Assche         {0x51, "HD DVD-R"},
135*44704f69SBart Van Assche         {0x52, "HD DVD-RAM"},
136*44704f69SBart Van Assche         {0x53, "HD DVD-RW"},
137*44704f69SBart Van Assche         {0x58, "HD DVD-R dual layer"},
138*44704f69SBart Van Assche         {0x5a, "HD DVD-RW dual layer"},
139*44704f69SBart Van Assche         {0xffff, "Non-conforming profile"},
140*44704f69SBart Van Assche         {-1, NULL},
141*44704f69SBart Van Assche };
142*44704f69SBart Van Assche 
143*44704f69SBart Van Assche static const char *
get_profile_str(int profile_num,char * buff)144*44704f69SBart Van Assche get_profile_str(int profile_num, char * buff)
145*44704f69SBart Van Assche {
146*44704f69SBart Van Assche     const struct val_desc_t * pdp;
147*44704f69SBart Van Assche 
148*44704f69SBart Van Assche     for (pdp = profile_desc_arr; pdp->desc; ++pdp) {
149*44704f69SBart Van Assche         if (pdp->val == profile_num) {
150*44704f69SBart Van Assche             strcpy(buff, pdp->desc);
151*44704f69SBart Van Assche             return buff;
152*44704f69SBart Van Assche         }
153*44704f69SBart Van Assche     }
154*44704f69SBart Van Assche     snprintf(buff, 64, "0x%x", profile_num);
155*44704f69SBart Van Assche     return buff;
156*44704f69SBart Van Assche }
157*44704f69SBart Van Assche 
158*44704f69SBart Van Assche static struct val_desc_t feature_desc_arr[] = {
159*44704f69SBart Van Assche         {0x0, "Profile list"},
160*44704f69SBart Van Assche         {0x1, "Core"},
161*44704f69SBart Van Assche         {0x2, "Morphing"},
162*44704f69SBart Van Assche         {0x3, "Removable media"},
163*44704f69SBart Van Assche         {0x4, "Write Protect"},
164*44704f69SBart Van Assche         {0x10, "Random readable"},
165*44704f69SBart Van Assche         {0x1d, "Multi-read"},
166*44704f69SBart Van Assche         {0x1e, "CD read"},
167*44704f69SBart Van Assche         {0x1f, "DVD read"},
168*44704f69SBart Van Assche         {0x20, "Random writable"},
169*44704f69SBart Van Assche         {0x21, "Incremental streaming writable"},
170*44704f69SBart Van Assche         {0x22, "Sector erasable"},
171*44704f69SBart Van Assche         {0x23, "Formattable"},
172*44704f69SBart Van Assche         {0x24, "Hardware defect management"},
173*44704f69SBart Van Assche         {0x25, "Write once"},
174*44704f69SBart Van Assche         {0x26, "Restricted overwrite"},
175*44704f69SBart Van Assche         {0x27, "CD-RW CAV write"},
176*44704f69SBart Van Assche         {0x28, "MRW"},          /* Mount Rainier reWritable */
177*44704f69SBart Van Assche         {0x29, "Enhanced defect reporting"},
178*44704f69SBart Van Assche         {0x2a, "DVD+RW"},
179*44704f69SBart Van Assche         {0x2b, "DVD+R"},
180*44704f69SBart Van Assche         {0x2c, "Rigid restricted overwrite"},
181*44704f69SBart Van Assche         {0x2d, "CD track-at-once"},
182*44704f69SBart Van Assche         {0x2e, "CD mastering (session at once)"},
183*44704f69SBart Van Assche         {0x2f, "DVD-R/-RW write"},
184*44704f69SBart Van Assche         {0x30, "Double density CD read"},
185*44704f69SBart Van Assche         {0x31, "Double density CD-R write"},
186*44704f69SBart Van Assche         {0x32, "Double density CD-RW write"},
187*44704f69SBart Van Assche         {0x33, "Layer jump recording"},
188*44704f69SBart Van Assche         {0x34, "LJ rigid restricted oberwrite"},
189*44704f69SBart Van Assche         {0x35, "Stop long operation"},
190*44704f69SBart Van Assche         {0x37, "CD-RW media write support"},
191*44704f69SBart Van Assche         {0x38, "BD-R POW"},
192*44704f69SBart Van Assche         {0x3a, "DVD+RW dual layer"},
193*44704f69SBart Van Assche         {0x3b, "DVD+R dual layer"},
194*44704f69SBart Van Assche         {0x40, "BD read"},
195*44704f69SBart Van Assche         {0x41, "BD write"},
196*44704f69SBart Van Assche         {0x42, "TSR (timely safe recording)"},
197*44704f69SBart Van Assche         {0x50, "HD DVD read"},
198*44704f69SBart Van Assche         {0x51, "HD DVD write"},
199*44704f69SBart Van Assche         {0x52, "HD DVD-RW fragment recording"},
200*44704f69SBart Van Assche         {0x80, "Hybrid disc"},
201*44704f69SBart Van Assche         {0x100, "Power management"},
202*44704f69SBart Van Assche         {0x101, "SMART"},
203*44704f69SBart Van Assche         {0x102, "Embedded changer"},
204*44704f69SBart Van Assche         {0x103, "CD audio external play"},
205*44704f69SBart Van Assche         {0x104, "Microcode upgrade"},
206*44704f69SBart Van Assche         {0x105, "Timeout"},
207*44704f69SBart Van Assche         {0x106, "DVD CSS"},
208*44704f69SBart Van Assche         {0x107, "Real time streaming"},
209*44704f69SBart Van Assche         {0x108, "Drive serial number"},
210*44704f69SBart Van Assche         {0x109, "Media serial number"},
211*44704f69SBart Van Assche         {0x10a, "Disc control blocks"},
212*44704f69SBart Van Assche         {0x10b, "DVD CPRM"},
213*44704f69SBart Van Assche         {0x10c, "Firmware information"},
214*44704f69SBart Van Assche         {0x10d, "AACS"},
215*44704f69SBart Van Assche         {0x10e, "DVD CSS managed recording"},
216*44704f69SBart Van Assche         {0x110, "VCPS"},
217*44704f69SBart Van Assche         {0x113, "SecurDisc"},
218*44704f69SBart Van Assche         {0x120, "BD CPS"},
219*44704f69SBart Van Assche         {0x142, "OSSC"},
220*44704f69SBart Van Assche };
221*44704f69SBart Van Assche 
222*44704f69SBart Van Assche static const char *
get_feature_str(int feature_num,char * buff)223*44704f69SBart Van Assche get_feature_str(int feature_num, char * buff)
224*44704f69SBart Van Assche {
225*44704f69SBart Van Assche     int k, num;
226*44704f69SBart Van Assche 
227*44704f69SBart Van Assche     num = SG_ARRAY_SIZE(feature_desc_arr);
228*44704f69SBart Van Assche     for (k = 0; k < num; ++k) {
229*44704f69SBart Van Assche         if (feature_desc_arr[k].val == feature_num) {
230*44704f69SBart Van Assche             strcpy(buff, feature_desc_arr[k].desc);
231*44704f69SBart Van Assche             return buff;
232*44704f69SBart Van Assche         }
233*44704f69SBart Van Assche     }
234*44704f69SBart Van Assche     snprintf(buff, 64, "0x%x", feature_num);
235*44704f69SBart Van Assche     return buff;
236*44704f69SBart Van Assche }
237*44704f69SBart Van Assche 
238*44704f69SBart Van Assche static void
dStrRaw(const char * str,int len)239*44704f69SBart Van Assche dStrRaw(const char * str, int len)
240*44704f69SBart Van Assche {
241*44704f69SBart Van Assche     int k;
242*44704f69SBart Van Assche 
243*44704f69SBart Van Assche     for (k = 0; k < len; ++k)
244*44704f69SBart Van Assche         printf("%c", str[k]);
245*44704f69SBart Van Assche }
246*44704f69SBart Van Assche 
247*44704f69SBart Van Assche static void
decode_feature(int feature,uint8_t * bp,int len)248*44704f69SBart Van Assche decode_feature(int feature, uint8_t * bp, int len)
249*44704f69SBart Van Assche {
250*44704f69SBart Van Assche     int k, num, n, profile;
251*44704f69SBart Van Assche     char buff[128];
252*44704f69SBart Van Assche     const char * cp;
253*44704f69SBart Van Assche 
254*44704f69SBart Van Assche     switch (feature) {
255*44704f69SBart Van Assche     case 0:     /* Profile list */
256*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
257*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 2), !!(bp[2] & 1),
258*44704f69SBart Van Assche                feature);
259*44704f69SBart Van Assche         printf("    available profiles [more recent typically higher "
260*44704f69SBart Van Assche                "in list]:\n");
261*44704f69SBart Van Assche         for (k = 4; k < len; k += 4) {
262*44704f69SBart Van Assche             profile = sg_get_unaligned_be16(bp + k);
263*44704f69SBart Van Assche             printf("      profile: %s , currentP=%d\n",
264*44704f69SBart Van Assche                    get_profile_str(profile, buff), !!(bp[k + 2] & 1));
265*44704f69SBart Van Assche         }
266*44704f69SBart Van Assche         break;
267*44704f69SBart Van Assche     case 1:     /* Core */
268*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
269*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 2), !!(bp[2] & 1),
270*44704f69SBart Van Assche                feature);
271*44704f69SBart Van Assche         if (len < 8) {
272*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
273*44704f69SBart Van Assche             break;
274*44704f69SBart Van Assche         }
275*44704f69SBart Van Assche         num = sg_get_unaligned_be32(bp + 4);
276*44704f69SBart Van Assche         switch (num) {
277*44704f69SBart Van Assche         case 0: cp = "unspecified"; break;
278*44704f69SBart Van Assche         case 1: cp = "SCSI family"; break;
279*44704f69SBart Van Assche         case 2: cp = "ATAPI"; break;
280*44704f69SBart Van Assche         case 3: cp = "IEEE 1394 - 1995"; break;
281*44704f69SBart Van Assche         case 4: cp = "IEEE 1394A"; break;
282*44704f69SBart Van Assche         case 5: cp = "Fibre channel"; break;
283*44704f69SBart Van Assche         case 6: cp = "IEEE 1394B"; break;
284*44704f69SBart Van Assche         case 7: cp = "Serial ATAPI"; break;
285*44704f69SBart Van Assche         case 8: cp = "USB (both 1 and 2)"; break;
286*44704f69SBart Van Assche         case 0xffff: cp = "vendor unique"; break;
287*44704f69SBart Van Assche         default:
288*44704f69SBart Van Assche             snprintf(buff, sizeof(buff), "[0x%x]", num);
289*44704f69SBart Van Assche             cp = buff;
290*44704f69SBart Van Assche             break;
291*44704f69SBart Van Assche         }
292*44704f69SBart Van Assche         printf("      Physical interface standard: %s", cp);
293*44704f69SBart Van Assche         if (len > 8)
294*44704f69SBart Van Assche             printf(", INQ2=%d, DBE=%d\n", !!(bp[8] & 2), !!(bp[8] & 1));
295*44704f69SBart Van Assche         else
296*44704f69SBart Van Assche             printf("\n");
297*44704f69SBart Van Assche         break;
298*44704f69SBart Van Assche     case 2:     /* Morphing */
299*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
300*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 2), !!(bp[2] & 1),
301*44704f69SBart Van Assche                feature);
302*44704f69SBart Van Assche         if (len < 8) {
303*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
304*44704f69SBart Van Assche             break;
305*44704f69SBart Van Assche         }
306*44704f69SBart Van Assche         printf("      OCEvent=%d, ASYNC=%d\n", !!(bp[4] & 2), !!(bp[4] & 1));
307*44704f69SBart Van Assche         break;
308*44704f69SBart Van Assche     case 3:     /* Removable medium */
309*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
310*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 2), !!(bp[2] & 1),
311*44704f69SBart Van Assche                feature);
312*44704f69SBart Van Assche         if (len < 8) {
313*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
314*44704f69SBart Van Assche             break;
315*44704f69SBart Van Assche         }
316*44704f69SBart Van Assche         num = (bp[4] >> 5) & 0x7;
317*44704f69SBart Van Assche         switch (num) {
318*44704f69SBart Van Assche         case 0: cp = "Caddy/slot type"; break;
319*44704f69SBart Van Assche         case 1: cp = "Tray type"; break;
320*44704f69SBart Van Assche         case 2: cp = "Pop-up type"; break;
321*44704f69SBart Van Assche         case 4: cp = "Embedded changer with individually changeable discs";
322*44704f69SBart Van Assche             break;
323*44704f69SBart Van Assche         case 5: cp = "Embedded changer using a magazine"; break;
324*44704f69SBart Van Assche         default:
325*44704f69SBart Van Assche             snprintf(buff, sizeof(buff), "[0x%x]", num);
326*44704f69SBart Van Assche             cp = buff;
327*44704f69SBart Van Assche             break;
328*44704f69SBart Van Assche         }
329*44704f69SBart Van Assche         printf("      Loading mechanism: %s\n", cp);
330*44704f69SBart Van Assche         printf("      Load=%d, Eject=%d, Prevent jumper=%d, Lock=%d\n",
331*44704f69SBart Van Assche                !!(bp[4] & 0x10), !!(bp[4] & 0x8), !!(bp[4] & 0x4),
332*44704f69SBart Van Assche                !!(bp[4] & 0x1));
333*44704f69SBart Van Assche         break;
334*44704f69SBart Van Assche     case 4:     /* Write protect */
335*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
336*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
337*44704f69SBart Van Assche                feature);
338*44704f69SBart Van Assche         if (len < 8) {
339*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
340*44704f69SBart Van Assche             break;
341*44704f69SBart Van Assche         }
342*44704f69SBart Van Assche         printf("      DWP=%d, WDCB=%d, SPWP=%d, SSWPP=%d\n", !!(bp[4] & 0x8),
343*44704f69SBart Van Assche                !!(bp[4] & 0x4), !!(bp[4] & 0x2), !!(bp[4] & 0x1));
344*44704f69SBart Van Assche         break;
345*44704f69SBart Van Assche     case 0x10:     /* Random readable */
346*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
347*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
348*44704f69SBart Van Assche                feature);
349*44704f69SBart Van Assche         if (len < 12) {
350*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
351*44704f69SBart Van Assche             break;
352*44704f69SBart Van Assche         }
353*44704f69SBart Van Assche         num = sg_get_unaligned_be32(bp + 4);
354*44704f69SBart Van Assche         printf("      Logical block size=0x%x, blocking=0x%x, PP=%d\n",
355*44704f69SBart Van Assche                num, sg_get_unaligned_be16(bp + 8), !!(bp[10] & 0x1));
356*44704f69SBart Van Assche         break;
357*44704f69SBart Van Assche     case 0x1d:     /* Multi-read */
358*44704f69SBart Van Assche     case 0x22:     /* Sector erasable */
359*44704f69SBart Van Assche     case 0x26:     /* Restricted overwrite */
360*44704f69SBart Van Assche     case 0x27:     /* CDRW CAV write */
361*44704f69SBart Van Assche     case 0x35:     /* Stop long operation */
362*44704f69SBart Van Assche     case 0x38:     /* BD-R pseudo-overwrite (POW) */
363*44704f69SBart Van Assche     case 0x42:     /* TSR (timely safe recording) */
364*44704f69SBart Van Assche     case 0x100:    /* Power management */
365*44704f69SBart Van Assche     case 0x109:    /* Media serial number */
366*44704f69SBart Van Assche     case 0x110:    /* VCPS */
367*44704f69SBart Van Assche     case 0x113:    /* SecurDisc */
368*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
369*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
370*44704f69SBart Van Assche                feature);
371*44704f69SBart Van Assche         break;
372*44704f69SBart Van Assche     case 0x1e:     /* CD read */
373*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
374*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
375*44704f69SBart Van Assche                feature);
376*44704f69SBart Van Assche         if (len < 8) {
377*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
378*44704f69SBart Van Assche             break;
379*44704f69SBart Van Assche         }
380*44704f69SBart Van Assche         printf("      DAP=%d, C2 flags=%d, CD-Text=%d\n", !!(bp[4] & 0x80),
381*44704f69SBart Van Assche                !!(bp[4] & 0x2), !!(bp[4] & 0x1));
382*44704f69SBart Van Assche         break;
383*44704f69SBart Van Assche     case 0x1f:     /* DVD read */
384*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
385*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
386*44704f69SBart Van Assche                feature);
387*44704f69SBart Van Assche         if (len > 7)
388*44704f69SBart Van Assche             printf("      MULTI110=%d, Dual-RW=%d, Dual-R=%d\n",
389*44704f69SBart Van Assche                    !!(bp[4] & 0x1), !!(bp[6] & 0x2), !!(bp[6] & 0x1));
390*44704f69SBart Van Assche         break;
391*44704f69SBart Van Assche     case 0x20:     /* Random writable */
392*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
393*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
394*44704f69SBart Van Assche                feature);
395*44704f69SBart Van Assche         if (len < 16) {
396*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
397*44704f69SBart Van Assche             break;
398*44704f69SBart Van Assche         }
399*44704f69SBart Van Assche         num = sg_get_unaligned_be32(bp + 4);
400*44704f69SBart Van Assche         n = sg_get_unaligned_be32(bp + 8);
401*44704f69SBart Van Assche         printf("      Last lba=0x%x, Logical block size=0x%x, blocking=0x%x,"
402*44704f69SBart Van Assche                " PP=%d\n", num, n, sg_get_unaligned_be16(bp + 12),
403*44704f69SBart Van Assche                !!(bp[14] & 0x1));
404*44704f69SBart Van Assche         break;
405*44704f69SBart Van Assche     case 0x21:     /* Incremental streaming writable */
406*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
407*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
408*44704f69SBart Van Assche                feature);
409*44704f69SBart Van Assche         if (len < 8) {
410*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
411*44704f69SBart Van Assche             break;
412*44704f69SBart Van Assche         }
413*44704f69SBart Van Assche         printf("      Data block types supported=0x%x, TRIO=%d, ARSV=%d, "
414*44704f69SBart Van Assche                "BUF=%d\n", sg_get_unaligned_be16(bp + 4), !!(bp[6] & 0x4),
415*44704f69SBart Van Assche                !!(bp[6] & 0x2), !!(bp[6] & 0x1));
416*44704f69SBart Van Assche         num = bp[7];
417*44704f69SBart Van Assche         printf("      Number of link sizes=%d\n", num);
418*44704f69SBart Van Assche         for (k = 0; k < num; ++k)
419*44704f69SBart Van Assche             printf("        %d\n", bp[8 + k]);
420*44704f69SBart Van Assche         break;
421*44704f69SBart Van Assche     /* case 0x22:     Sector erasable -> see 0x1d entry */
422*44704f69SBart Van Assche     case 0x23:     /* Formattable */
423*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
424*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
425*44704f69SBart Van Assche                feature);
426*44704f69SBart Van Assche         if (len > 4)
427*44704f69SBart Van Assche             printf("      BD-RE: RENoSA=%d, Expand=%d, QCert=%d, Cert=%d, "
428*44704f69SBart Van Assche                    "FRF=%d\n", !!(bp[4] & 0x8), !!(bp[4] & 0x4),
429*44704f69SBart Van Assche                    !!(bp[4] & 0x2), !!(bp[4] & 0x1), !!(bp[5] & 0x80));
430*44704f69SBart Van Assche         if (len > 8)
431*44704f69SBart Van Assche             printf("      BD-R: RRM=%d\n", !!(bp[8] & 0x1));
432*44704f69SBart Van Assche         break;
433*44704f69SBart Van Assche     case 0x24:     /* Hardware defect management */
434*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
435*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
436*44704f69SBart Van Assche                feature);
437*44704f69SBart Van Assche         if (len > 4)
438*44704f69SBart Van Assche             printf("      SSA=%d\n", !!(bp[4] & 0x80));
439*44704f69SBart Van Assche         break;
440*44704f69SBart Van Assche     case 0x25:     /* Write once */
441*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
442*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
443*44704f69SBart Van Assche                feature);
444*44704f69SBart Van Assche         if (len < 12) {
445*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
446*44704f69SBart Van Assche             break;
447*44704f69SBart Van Assche         }
448*44704f69SBart Van Assche         num = sg_get_unaligned_be16(bp + 4);
449*44704f69SBart Van Assche         printf("      Logical block size=0x%x, blocking=0x%x, PP=%d\n",
450*44704f69SBart Van Assche                num, sg_get_unaligned_be16(bp + 8), !!(bp[10] & 0x1));
451*44704f69SBart Van Assche         break;
452*44704f69SBart Van Assche     /* case 0x26:     Restricted overwrite -> see 0x1d entry */
453*44704f69SBart Van Assche     /* case 0x27:     CDRW CAV write -> see 0x1d entry */
454*44704f69SBart Van Assche     case 0x28:     /* MRW  (Mount Rainier reWriteable) */
455*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
456*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
457*44704f69SBart Van Assche                feature);
458*44704f69SBart Van Assche         if (len > 4)
459*44704f69SBart Van Assche             printf("      DVD+Write=%d, DVD+Read=%d, Write=%d\n",
460*44704f69SBart Van Assche                    !!(bp[4] & 0x4), !!(bp[4] & 0x2), !!(bp[4] & 0x1));
461*44704f69SBart Van Assche         break;
462*44704f69SBart Van Assche     case 0x29:     /* Enhanced defect reporting */
463*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
464*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
465*44704f69SBart Van Assche                feature);
466*44704f69SBart Van Assche         if (len < 8) {
467*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
468*44704f69SBart Van Assche             break;
469*44704f69SBart Van Assche         }
470*44704f69SBart Van Assche         printf("      DRT-DM=%d, number of DBI cache zones=0x%x, number of "
471*44704f69SBart Van Assche                "entries=0x%x\n", !!(bp[4] & 0x1), bp[5],
472*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 6));
473*44704f69SBart Van Assche         break;
474*44704f69SBart Van Assche     case 0x2a:     /* DVD+RW */
475*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
476*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
477*44704f69SBart Van Assche                feature);
478*44704f69SBart Van Assche         if (len < 8) {
479*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
480*44704f69SBart Van Assche             break;
481*44704f69SBart Van Assche         }
482*44704f69SBart Van Assche         printf("      Write=%d, Quick start=%d, Close only=%d\n",
483*44704f69SBart Van Assche                !!(bp[4] & 0x1), !!(bp[5] & 0x2), !!(bp[5] & 0x1));
484*44704f69SBart Van Assche         break;
485*44704f69SBart Van Assche     case 0x2b:     /* DVD+R */
486*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
487*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
488*44704f69SBart Van Assche                feature);
489*44704f69SBart Van Assche         if (len < 8) {
490*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
491*44704f69SBart Van Assche             break;
492*44704f69SBart Van Assche         }
493*44704f69SBart Van Assche         printf("      Write=%d\n", !!(bp[4] & 0x1));
494*44704f69SBart Van Assche         break;
495*44704f69SBart Van Assche     case 0x2c:     /* Rigid restricted overwrite */
496*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
497*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
498*44704f69SBart Van Assche                feature);
499*44704f69SBart Van Assche         if (len < 8) {
500*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
501*44704f69SBart Van Assche             break;
502*44704f69SBart Van Assche         }
503*44704f69SBart Van Assche         printf("      DSDG=%d, DSDR=%d, Intermediate=%d, Blank=%d\n",
504*44704f69SBart Van Assche                !!(bp[4] & 0x8), !!(bp[4] & 0x4), !!(bp[4] & 0x2),
505*44704f69SBart Van Assche                !!(bp[4] & 0x1));
506*44704f69SBart Van Assche         break;
507*44704f69SBart Van Assche     case 0x2d:     /* CD Track at once */
508*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
509*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
510*44704f69SBart Van Assche                feature);
511*44704f69SBart Van Assche         if (len < 8) {
512*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
513*44704f69SBart Van Assche             break;
514*44704f69SBart Van Assche         }
515*44704f69SBart Van Assche         printf("      BUF=%d, R-W raw=%d, R-W pack=%d, Test write=%d\n",
516*44704f69SBart Van Assche                !!(bp[4] & 0x40), !!(bp[4] & 0x10), !!(bp[4] & 0x8),
517*44704f69SBart Van Assche                !!(bp[4] & 0x4));
518*44704f69SBart Van Assche         printf("      CD-RW=%d, R-W sub-code=%d, Data type supported=%d\n",
519*44704f69SBart Van Assche                !!(bp[4] & 0x2), !!(bp[4] & 0x1),
520*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 6));
521*44704f69SBart Van Assche         break;
522*44704f69SBart Van Assche     case 0x2e:     /* CD mastering (session at once) */
523*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
524*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
525*44704f69SBart Van Assche                feature);
526*44704f69SBart Van Assche         if (len < 8) {
527*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
528*44704f69SBart Van Assche             break;
529*44704f69SBart Van Assche         }
530*44704f69SBart Van Assche         printf("      BUF=%d, SAO=%d, Raw MS=%d, Raw=%d\n",
531*44704f69SBart Van Assche                !!(bp[4] & 0x40), !!(bp[4] & 0x20), !!(bp[4] & 0x10),
532*44704f69SBart Van Assche                !!(bp[4] & 0x8));
533*44704f69SBart Van Assche         printf("      Test write=%d, CD-RW=%d, R-W=%d\n",
534*44704f69SBart Van Assche                !!(bp[4] & 0x4), !!(bp[4] & 0x2), !!(bp[4] & 0x1));
535*44704f69SBart Van Assche         printf("      Maximum cue sheet length=0x%x\n",
536*44704f69SBart Van Assche                sg_get_unaligned_be24(bp + 5));
537*44704f69SBart Van Assche         break;
538*44704f69SBart Van Assche     case 0x2f:     /* DVD-R/-RW write */
539*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
540*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
541*44704f69SBart Van Assche                feature);
542*44704f69SBart Van Assche         if (len < 8) {
543*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
544*44704f69SBart Van Assche             break;
545*44704f69SBart Van Assche         }
546*44704f69SBart Van Assche         printf("      BUF=%d, RDL=%d, Test write=%d, DVD-RW SL=%d\n",
547*44704f69SBart Van Assche                !!(bp[4] & 0x40), !!(bp[4] & 0x8), !!(bp[4] & 0x4),
548*44704f69SBart Van Assche                !!(bp[4] & 0x2));
549*44704f69SBart Van Assche         break;
550*44704f69SBart Van Assche     case 0x33:     /* Layer jump recording */
551*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
552*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
553*44704f69SBart Van Assche                feature);
554*44704f69SBart Van Assche         if (len < 8) {
555*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
556*44704f69SBart Van Assche             break;
557*44704f69SBart Van Assche         }
558*44704f69SBart Van Assche         num = bp[7];
559*44704f69SBart Van Assche         printf("      Number of link sizes=%d\n", num);
560*44704f69SBart Van Assche         for (k = 0; k < num; ++k)
561*44704f69SBart Van Assche             printf("        %d\n", bp[8 + k]);
562*44704f69SBart Van Assche         break;
563*44704f69SBart Van Assche     case 0x34:     /* Layer jump rigid restricted overwrite */
564*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
565*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
566*44704f69SBart Van Assche                feature);
567*44704f69SBart Van Assche         if (len < 8) {
568*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
569*44704f69SBart Van Assche             break;
570*44704f69SBart Van Assche         }
571*44704f69SBart Van Assche         printf("      CLJB=%d\n", !!(bp[4] & 0x1));
572*44704f69SBart Van Assche         printf("      Buffer block size=%d\n", bp[7]);
573*44704f69SBart Van Assche         break;
574*44704f69SBart Van Assche     /* case 0x35:     Stop long operation -> see 0x1d entry */
575*44704f69SBart Van Assche     case 0x37:     /* CD-RW media write support */
576*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
577*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
578*44704f69SBart Van Assche                feature);
579*44704f69SBart Van Assche         if (len < 8) {
580*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
581*44704f69SBart Van Assche             break;
582*44704f69SBart Van Assche         }
583*44704f69SBart Van Assche         printf("      CD-RW media sub-type support (bitmask)=0x%x\n", bp[5]);
584*44704f69SBart Van Assche         break;
585*44704f69SBart Van Assche     /* case 0x38:     BD-R pseudo-overwrite (POW) -> see 0x1d entry */
586*44704f69SBart Van Assche     case 0x3a:     /* DVD+RW dual layer */
587*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
588*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
589*44704f69SBart Van Assche                feature);
590*44704f69SBart Van Assche         if (len < 8) {
591*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
592*44704f69SBart Van Assche             break;
593*44704f69SBart Van Assche         }
594*44704f69SBart Van Assche         printf("      write=%d, quick_start=%d, close_only=%d\n",
595*44704f69SBart Van Assche                !!(bp[4] & 0x1), !!(bp[5] & 0x2), !!(bp[5] & 0x1));
596*44704f69SBart Van Assche         break;
597*44704f69SBart Van Assche     case 0x3b:     /* DVD+R dual layer */
598*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
599*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
600*44704f69SBart Van Assche                feature);
601*44704f69SBart Van Assche         if (len < 8) {
602*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
603*44704f69SBart Van Assche             break;
604*44704f69SBart Van Assche         }
605*44704f69SBart Van Assche         printf("      write=%d\n", !!(bp[4] & 0x1));
606*44704f69SBart Van Assche         break;
607*44704f69SBart Van Assche     case 0x40:     /* BD Read */
608*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
609*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
610*44704f69SBart Van Assche                feature);
611*44704f69SBart Van Assche         if (len < 32) {
612*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
613*44704f69SBart Van Assche             break;
614*44704f69SBart Van Assche         }
615*44704f69SBart Van Assche         printf("      Bitmaps for BD-RE read support:\n");
616*44704f69SBart Van Assche         printf("        Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, "
617*44704f69SBart Van Assche                "Class 3=0x%x\n", sg_get_unaligned_be16(bp + 8),
618*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 10),
619*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 12),
620*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 14));
621*44704f69SBart Van Assche         printf("      Bitmaps for BD-R read support:\n");
622*44704f69SBart Van Assche         printf("        Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, "
623*44704f69SBart Van Assche                "Class 3=0x%x\n", sg_get_unaligned_be16(bp + 16),
624*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 18),
625*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 20),
626*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 22));
627*44704f69SBart Van Assche         printf("      Bitmaps for BD-ROM read support:\n");
628*44704f69SBart Van Assche         printf("        Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, "
629*44704f69SBart Van Assche                "Class 3=0x%x\n", sg_get_unaligned_be16(bp + 24),
630*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 26),
631*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 28),
632*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 30));
633*44704f69SBart Van Assche         break;
634*44704f69SBart Van Assche     case 0x41:     /* BD Write */
635*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
636*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
637*44704f69SBart Van Assche                feature);
638*44704f69SBart Van Assche         if (len < 32) {
639*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
640*44704f69SBart Van Assche             break;
641*44704f69SBart Van Assche         }
642*44704f69SBart Van Assche         printf("      SVNR=%d\n", !!(bp[4] & 0x1));
643*44704f69SBart Van Assche         printf("      Bitmaps for BD-RE write support:\n");
644*44704f69SBart Van Assche         printf("        Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, "
645*44704f69SBart Van Assche                "Class 3=0x%x\n", sg_get_unaligned_be16(bp + 8),
646*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 10),
647*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 12),
648*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 14));
649*44704f69SBart Van Assche         printf("      Bitmaps for BD-R write support:\n");
650*44704f69SBart Van Assche         printf("        Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, "
651*44704f69SBart Van Assche                "Class 3=0x%x\n", sg_get_unaligned_be16(bp + 16),
652*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 18),
653*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 20),
654*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 22));
655*44704f69SBart Van Assche         printf("      Bitmaps for BD-ROM write support:\n");
656*44704f69SBart Van Assche         printf("        Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, "
657*44704f69SBart Van Assche                "Class 3=0x%x\n", sg_get_unaligned_be16(bp + 24),
658*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 26),
659*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 28),
660*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 30));
661*44704f69SBart Van Assche         break;
662*44704f69SBart Van Assche     /* case 0x42:     TSR (timely safe recording) -> see 0x1d entry */
663*44704f69SBart Van Assche     case 0x50:     /* HD DVD Read */
664*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
665*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
666*44704f69SBart Van Assche                feature);
667*44704f69SBart Van Assche         if (len < 8) {
668*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
669*44704f69SBart Van Assche             break;
670*44704f69SBart Van Assche         }
671*44704f69SBart Van Assche         printf("      HD DVD-R=%d, HD DVD-RAM=%d\n", !!(bp[4] & 0x1),
672*44704f69SBart Van Assche                !!(bp[6] & 0x1));
673*44704f69SBart Van Assche         break;
674*44704f69SBart Van Assche     case 0x51:     /* HD DVD Write */
675*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
676*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
677*44704f69SBart Van Assche                feature);
678*44704f69SBart Van Assche         if (len < 8) {
679*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
680*44704f69SBart Van Assche             break;
681*44704f69SBart Van Assche         }
682*44704f69SBart Van Assche         printf("      HD DVD-R=%d, HD DVD-RAM=%d\n", !!(bp[4] & 0x1),
683*44704f69SBart Van Assche                !!(bp[6] & 0x1));
684*44704f69SBart Van Assche         break;
685*44704f69SBart Van Assche     case 0x52:     /* HD DVD-RW fragment recording */
686*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
687*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
688*44704f69SBart Van Assche                feature);
689*44704f69SBart Van Assche         if (len < 8) {
690*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
691*44704f69SBart Van Assche             break;
692*44704f69SBart Van Assche         }
693*44704f69SBart Van Assche         printf("      BGP=%d\n", !!(bp[4] & 0x1));
694*44704f69SBart Van Assche         break;
695*44704f69SBart Van Assche     case 0x80:     /* Hybrid disc */
696*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
697*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
698*44704f69SBart Van Assche                feature);
699*44704f69SBart Van Assche         if (len < 8) {
700*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
701*44704f69SBart Van Assche             break;
702*44704f69SBart Van Assche         }
703*44704f69SBart Van Assche         printf("      RI=%d\n", !!(bp[4] & 0x1));
704*44704f69SBart Van Assche         break;
705*44704f69SBart Van Assche     /* case 0x100:    Power management -> see 0x1d entry */
706*44704f69SBart Van Assche     case 0x101:    /* SMART */
707*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
708*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
709*44704f69SBart Van Assche                feature);
710*44704f69SBart Van Assche         if (len < 8) {
711*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
712*44704f69SBart Van Assche             break;
713*44704f69SBart Van Assche         }
714*44704f69SBart Van Assche         printf("      PP=%d\n", !!(bp[4] & 0x1));
715*44704f69SBart Van Assche         break;
716*44704f69SBart Van Assche     case 0x102:    /* Embedded changer */
717*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
718*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
719*44704f69SBart Van Assche                feature);
720*44704f69SBart Van Assche         if (len < 8) {
721*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
722*44704f69SBart Van Assche             break;
723*44704f69SBart Van Assche         }
724*44704f69SBart Van Assche         printf("      SCC=%d, SDP=%d, highest slot number=%d\n",
725*44704f69SBart Van Assche                !!(bp[4] & 0x10), !!(bp[4] & 0x4), (bp[7] & 0x1f));
726*44704f69SBart Van Assche         break;
727*44704f69SBart Van Assche     case 0x103:    /* CD audio external play (obsolete) */
728*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
729*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
730*44704f69SBart Van Assche                feature);
731*44704f69SBart Van Assche         if (len < 8) {
732*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
733*44704f69SBart Van Assche             break;
734*44704f69SBart Van Assche         }
735*44704f69SBart Van Assche         printf("      Scan=%d, SCM=%d, SV=%d, number of volume levels=%d\n",
736*44704f69SBart Van Assche                !!(bp[4] & 0x4), !!(bp[4] & 0x2), !!(bp[4] & 0x1),
737*44704f69SBart Van Assche                sg_get_unaligned_be16(bp + 6));
738*44704f69SBart Van Assche         break;
739*44704f69SBart Van Assche     case 0x104:    /* Firmware upgrade */
740*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
741*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
742*44704f69SBart Van Assche                feature);
743*44704f69SBart Van Assche         if (len < 4) {
744*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
745*44704f69SBart Van Assche             break;
746*44704f69SBart Van Assche         }
747*44704f69SBart Van Assche         if (len > 4)
748*44704f69SBart Van Assche             printf("      M5=%d\n", !!(bp[4] & 0x1));
749*44704f69SBart Van Assche         break;
750*44704f69SBart Van Assche     case 0x105:    /* Timeout */
751*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
752*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
753*44704f69SBart Van Assche                feature);
754*44704f69SBart Van Assche         if (len > 7) {
755*44704f69SBart Van Assche             printf("      Group 3=%d, unit length=%d\n",
756*44704f69SBart Van Assche                    !!(bp[4] & 0x1), sg_get_unaligned_be16(bp + 6));
757*44704f69SBart Van Assche         }
758*44704f69SBart Van Assche         break;
759*44704f69SBart Van Assche     case 0x106:    /* DVD CSS */
760*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
761*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
762*44704f69SBart Van Assche                feature);
763*44704f69SBart Van Assche         if (len < 8) {
764*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
765*44704f69SBart Van Assche             break;
766*44704f69SBart Van Assche         }
767*44704f69SBart Van Assche         printf("      CSS version=%d\n", bp[7]);
768*44704f69SBart Van Assche         break;
769*44704f69SBart Van Assche     case 0x107:    /* Real time streaming */
770*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
771*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
772*44704f69SBart Van Assche                feature);
773*44704f69SBart Van Assche         if (len < 8) {
774*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
775*44704f69SBart Van Assche             break;
776*44704f69SBart Van Assche         }
777*44704f69SBart Van Assche         printf("      RBCB=%d, SCS=%d, MP2A=%d, WSPD=%d, SW=%d\n",
778*44704f69SBart Van Assche                !!(bp[4] & 0x10), !!(bp[4] & 0x8), !!(bp[4] & 0x4),
779*44704f69SBart Van Assche                !!(bp[4] & 0x2), !!(bp[4] & 0x1));
780*44704f69SBart Van Assche         break;
781*44704f69SBart Van Assche     case 0x108:    /* Drive serial number */
782*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
783*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
784*44704f69SBart Van Assche                feature);
785*44704f69SBart Van Assche         num = len - 4;
786*44704f69SBart Van Assche         n = sizeof(buff) - 1;
787*44704f69SBart Van Assche         n = ((num < n) ? num : n);
788*44704f69SBart Van Assche         strncpy(buff, (const char *)(bp + 4), n);
789*44704f69SBart Van Assche         buff[n] = '\0';
790*44704f69SBart Van Assche         printf("      Drive serial number: %s\n", buff);
791*44704f69SBart Van Assche         break;
792*44704f69SBart Van Assche     /* case 0x109:    Media serial number -> see 0x1d entry */
793*44704f69SBart Van Assche     case 0x10a:    /* Disc control blocks */
794*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
795*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
796*44704f69SBart Van Assche                feature);
797*44704f69SBart Van Assche         printf("      Disc control blocks:\n");
798*44704f69SBart Van Assche         for (k = 4; k < len; k += 4) {
799*44704f69SBart Van Assche             printf("        0x%x\n", sg_get_unaligned_be32(bp + k));
800*44704f69SBart Van Assche         }
801*44704f69SBart Van Assche         break;
802*44704f69SBart Van Assche     case 0x10b:    /* DVD CPRM */
803*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
804*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
805*44704f69SBart Van Assche                feature);
806*44704f69SBart Van Assche         if (len < 8) {
807*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
808*44704f69SBart Van Assche             break;
809*44704f69SBart Van Assche         }
810*44704f69SBart Van Assche         printf("      CPRM version=%d\n", bp[7]);
811*44704f69SBart Van Assche         break;
812*44704f69SBart Van Assche     case 0x10c:    /* firmware information */
813*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
814*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
815*44704f69SBart Van Assche                feature);
816*44704f69SBart Van Assche         if (len < 20) {
817*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
818*44704f69SBart Van Assche             break;
819*44704f69SBart Van Assche         }
820*44704f69SBart Van Assche         printf("      %.2s%.2s/%.2s/%.2s %.2s:%.2s:%.2s\n", bp + 4,
821*44704f69SBart Van Assche                bp + 6, bp + 8, bp + 10, bp + 12, bp + 14, bp + 16);
822*44704f69SBart Van Assche         break;
823*44704f69SBart Van Assche     case 0x10d:    /* AACS */
824*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
825*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
826*44704f69SBart Van Assche                feature);
827*44704f69SBart Van Assche         if (len < 8) {
828*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
829*44704f69SBart Van Assche             break;
830*44704f69SBart Van Assche         }
831*44704f69SBart Van Assche         printf("      BNG=%d, Block count for binding nonce=%d\n",
832*44704f69SBart Van Assche                !!(bp[4] & 0x1), bp[5]);
833*44704f69SBart Van Assche         printf("      Number of AGIDs=%d, AACS version=%d\n",
834*44704f69SBart Van Assche                (bp[6] & 0xf), bp[7]);
835*44704f69SBart Van Assche         break;
836*44704f69SBart Van Assche     case 0x10e:    /* DVD CSS managed recording */
837*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
838*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
839*44704f69SBart Van Assche                feature);
840*44704f69SBart Van Assche         if (len < 8) {
841*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
842*44704f69SBart Van Assche             break;
843*44704f69SBart Van Assche         }
844*44704f69SBart Van Assche         printf("      Maximum number of scrambled extent information "
845*44704f69SBart Van Assche                "entries=%d\n", bp[4]);
846*44704f69SBart Van Assche         break;
847*44704f69SBart Van Assche     /* case 0x110:    VCPS -> see 0x1d entry */
848*44704f69SBart Van Assche     /* case 0x113:    SecurDisc -> see 0x1d entry */
849*44704f69SBart Van Assche     case 0x120:    /* BD CPS */
850*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
851*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
852*44704f69SBart Van Assche                feature);
853*44704f69SBart Van Assche         if (len < 8) {
854*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
855*44704f69SBart Van Assche             break;
856*44704f69SBart Van Assche         }
857*44704f69SBart Van Assche         printf("      BD CPS major:minor version number=%d:%d, max open "
858*44704f69SBart Van Assche                "SACs=%d\n", ((bp[5] >> 4) & 0xf), (bp[5] & 0xf),
859*44704f69SBart Van Assche                bp[6] & 0x3);
860*44704f69SBart Van Assche         break;
861*44704f69SBart Van Assche     case 0x142:    /* OSSC (Optical Security Subsystem Class) */
862*44704f69SBart Van Assche         printf("    version=%d, persist=%d, current=%d [0x%x]\n",
863*44704f69SBart Van Assche                ((bp[2] >> 2) & 0xf), !!(bp[2] & 0x2), !!(bp[2] & 0x1),
864*44704f69SBart Van Assche                feature);
865*44704f69SBart Van Assche         if (len < 8) {
866*44704f69SBart Van Assche             printf("      additional length [%d] too short\n", len - 4);
867*44704f69SBart Van Assche             break;
868*44704f69SBart Van Assche         }
869*44704f69SBart Van Assche         printf("    PSAU=%d, LOSPB=%d, ME=%d\n", !!(bp[4] & 0x80),
870*44704f69SBart Van Assche                !!(bp[4] & 0x40), !!(bp[4] & 0x1));
871*44704f69SBart Van Assche         num = bp[5];
872*44704f69SBart Van Assche         printf("      Profile numbers:\n");
873*44704f69SBart Van Assche         for (k = 6; (num > 0) && (k < len); --num, k += 2) {
874*44704f69SBart Van Assche             printf("        %u\n", sg_get_unaligned_be16(bp + k));
875*44704f69SBart Van Assche         }
876*44704f69SBart Van Assche         break;
877*44704f69SBart Van Assche     default:
878*44704f69SBart Van Assche         pr2serr("    Unknown feature [0x%x], version=%d persist=%d, "
879*44704f69SBart Van Assche                 "current=%d\n", feature, ((bp[2] >> 2) & 0xf),
880*44704f69SBart Van Assche                 !!(bp[2] & 0x2), !!(bp[2] & 0x1));
881*44704f69SBart Van Assche         hex2stderr(bp, len, 1);
882*44704f69SBart Van Assche         break;
883*44704f69SBart Van Assche     }
884*44704f69SBart Van Assche }
885*44704f69SBart Van Assche 
886*44704f69SBart Van Assche static void
decode_config(uint8_t * resp,int max_resp_len,int len,bool brief,bool inner_hex)887*44704f69SBart Van Assche decode_config(uint8_t * resp, int max_resp_len, int len, bool brief,
888*44704f69SBart Van Assche               bool inner_hex)
889*44704f69SBart Van Assche {
890*44704f69SBart Van Assche     int k, curr_profile, extra_len, feature;
891*44704f69SBart Van Assche     uint8_t * bp;
892*44704f69SBart Van Assche     char buff[128];
893*44704f69SBart Van Assche 
894*44704f69SBart Van Assche     if (max_resp_len < len) {
895*44704f69SBart Van Assche         pr2serr("<<<warning: response to long for buffer, resp_len=%d>>>\n",
896*44704f69SBart Van Assche                 len);
897*44704f69SBart Van Assche             len = max_resp_len;
898*44704f69SBart Van Assche     }
899*44704f69SBart Van Assche     if (len < 8) {
900*44704f69SBart Van Assche         pr2serr("response length too short: %d\n", len);
901*44704f69SBart Van Assche         return;
902*44704f69SBart Van Assche     }
903*44704f69SBart Van Assche     curr_profile = sg_get_unaligned_be16(resp + 6);
904*44704f69SBart Van Assche     if (0 == curr_profile)
905*44704f69SBart Van Assche         pr2serr("No current profile\n");
906*44704f69SBart Van Assche     else
907*44704f69SBart Van Assche         printf("Current profile: %s\n", get_profile_str(curr_profile, buff));
908*44704f69SBart Van Assche     printf("Features%s:\n", (brief ? " (in brief)" : ""));
909*44704f69SBart Van Assche     bp = resp + 8;
910*44704f69SBart Van Assche     len -= 8;
911*44704f69SBart Van Assche     for (k = 0; k < len; k += extra_len, bp += extra_len) {
912*44704f69SBart Van Assche         extra_len = 4 + bp[3];
913*44704f69SBart Van Assche         feature = sg_get_unaligned_be16(bp + 0);
914*44704f69SBart Van Assche         printf("  %s feature\n", get_feature_str(feature, buff));
915*44704f69SBart Van Assche         if (brief)
916*44704f69SBart Van Assche             continue;
917*44704f69SBart Van Assche         if (inner_hex) {
918*44704f69SBart Van Assche             hex2stdout(bp, extra_len, 1);
919*44704f69SBart Van Assche             continue;
920*44704f69SBart Van Assche         }
921*44704f69SBart Van Assche         if (0 != (extra_len % 4))
922*44704f69SBart Van Assche             printf("    additional length [%d] not a multiple of 4, ignore\n",
923*44704f69SBart Van Assche                    extra_len - 4);
924*44704f69SBart Van Assche         else
925*44704f69SBart Van Assche             decode_feature(feature, bp, extra_len);
926*44704f69SBart Van Assche     }
927*44704f69SBart Van Assche }
928*44704f69SBart Van Assche 
929*44704f69SBart Van Assche static void
list_known(bool brief)930*44704f69SBart Van Assche list_known(bool brief)
931*44704f69SBart Van Assche {
932*44704f69SBart Van Assche     int k, num;
933*44704f69SBart Van Assche 
934*44704f69SBart Van Assche     num = SG_ARRAY_SIZE(feature_desc_arr);
935*44704f69SBart Van Assche     printf("Known features:\n");
936*44704f69SBart Van Assche     for (k = 0; k < num; ++k)
937*44704f69SBart Van Assche         printf("  %s [0x%x]\n", feature_desc_arr[k].desc,
938*44704f69SBart Van Assche                feature_desc_arr[k].val);
939*44704f69SBart Van Assche     if (! brief) {
940*44704f69SBart Van Assche         printf("Known profiles:\n");
941*44704f69SBart Van Assche         num = SG_ARRAY_SIZE(profile_desc_arr);
942*44704f69SBart Van Assche         for (k = 0; k < num; ++k)
943*44704f69SBart Van Assche             printf("  %s [0x%x]\n", profile_desc_arr[k].desc,
944*44704f69SBart Van Assche                    profile_desc_arr[k].val);
945*44704f69SBart Van Assche     }
946*44704f69SBart Van Assche }
947*44704f69SBart Van Assche 
948*44704f69SBart Van Assche 
949*44704f69SBart Van Assche int
main(int argc,char * argv[])950*44704f69SBart Van Assche main(int argc, char * argv[])
951*44704f69SBart Van Assche {
952*44704f69SBart Van Assche     bool brief = false;
953*44704f69SBart Van Assche     bool inner_hex = false;
954*44704f69SBart Van Assche     bool list = false;
955*44704f69SBart Van Assche     bool do_raw = false;
956*44704f69SBart Van Assche     bool readonly = false;
957*44704f69SBart Van Assche     bool verbose_given = false;
958*44704f69SBart Van Assche     bool version_given = false;
959*44704f69SBart Van Assche     int sg_fd, res, c, len;
960*44704f69SBart Van Assche     int peri_type = 0;
961*44704f69SBart Van Assche     int rt = 0;
962*44704f69SBart Van Assche     int starting = 0;
963*44704f69SBart Van Assche     int verbose = 0;
964*44704f69SBart Van Assche     int do_hex = 0;
965*44704f69SBart Van Assche     const char * device_name = NULL;
966*44704f69SBart Van Assche     char buff[64];
967*44704f69SBart Van Assche     const char * cp;
968*44704f69SBart Van Assche     struct sg_simple_inquiry_resp inq_resp;
969*44704f69SBart Van Assche     int ret = 0;
970*44704f69SBart Van Assche 
971*44704f69SBart Van Assche     while (1) {
972*44704f69SBart Van Assche         int option_index = 0;
973*44704f69SBart Van Assche 
974*44704f69SBart Van Assche         c = getopt_long(argc, argv, "bchHilqr:Rs:vV", long_options,
975*44704f69SBart Van Assche                         &option_index);
976*44704f69SBart Van Assche         if (c == -1)
977*44704f69SBart Van Assche             break;
978*44704f69SBart Van Assche 
979*44704f69SBart Van Assche         switch (c) {
980*44704f69SBart Van Assche         case 'b':
981*44704f69SBart Van Assche             brief = true;
982*44704f69SBart Van Assche             break;
983*44704f69SBart Van Assche         case 'c':
984*44704f69SBart Van Assche             rt = 1;
985*44704f69SBart Van Assche             break;
986*44704f69SBart Van Assche         case 'h':
987*44704f69SBart Van Assche         case '?':
988*44704f69SBart Van Assche             usage();
989*44704f69SBart Van Assche             return 0;
990*44704f69SBart Van Assche         case 'H':
991*44704f69SBart Van Assche             ++do_hex;
992*44704f69SBart Van Assche             break;
993*44704f69SBart Van Assche         case 'i':
994*44704f69SBart Van Assche             inner_hex = true;
995*44704f69SBart Van Assche             break;
996*44704f69SBart Van Assche         case 'l':
997*44704f69SBart Van Assche             list = true;
998*44704f69SBart Van Assche             break;
999*44704f69SBart Van Assche         case 'q':
1000*44704f69SBart Van Assche             readonly = true;
1001*44704f69SBart Van Assche             break;
1002*44704f69SBart Van Assche         case 'r':
1003*44704f69SBart Van Assche             rt = sg_get_num(optarg);
1004*44704f69SBart Van Assche             if ((rt < 0) || (rt > 3)) {
1005*44704f69SBart Van Assche                 pr2serr("bad argument to '--rt'\n");
1006*44704f69SBart Van Assche                 return SG_LIB_SYNTAX_ERROR;
1007*44704f69SBart Van Assche             }
1008*44704f69SBart Van Assche             break;
1009*44704f69SBart Van Assche         case 'R':
1010*44704f69SBart Van Assche             do_raw = true;
1011*44704f69SBart Van Assche             break;
1012*44704f69SBart Van Assche         case 's':
1013*44704f69SBart Van Assche             starting = sg_get_num(optarg);
1014*44704f69SBart Van Assche             if ((starting < 0) || (starting > 0xffff)) {
1015*44704f69SBart Van Assche                 pr2serr("bad argument to '--starting'\n");
1016*44704f69SBart Van Assche                 return SG_LIB_SYNTAX_ERROR;
1017*44704f69SBart Van Assche             }
1018*44704f69SBart Van Assche             break;
1019*44704f69SBart Van Assche         case 'v':
1020*44704f69SBart Van Assche             verbose_given = true;
1021*44704f69SBart Van Assche             ++verbose;
1022*44704f69SBart Van Assche             break;
1023*44704f69SBart Van Assche         case 'V':
1024*44704f69SBart Van Assche             version_given = true;
1025*44704f69SBart Van Assche             break;
1026*44704f69SBart Van Assche         default:
1027*44704f69SBart Van Assche             pr2serr("unrecognised option code 0x%x ??\n", c);
1028*44704f69SBart Van Assche             usage();
1029*44704f69SBart Van Assche             return SG_LIB_SYNTAX_ERROR;
1030*44704f69SBart Van Assche         }
1031*44704f69SBart Van Assche     }
1032*44704f69SBart Van Assche     if (optind < argc) {
1033*44704f69SBart Van Assche         if (NULL == device_name) {
1034*44704f69SBart Van Assche             device_name = argv[optind];
1035*44704f69SBart Van Assche             ++optind;
1036*44704f69SBart Van Assche         }
1037*44704f69SBart Van Assche         if (optind < argc) {
1038*44704f69SBart Van Assche             for (; optind < argc; ++optind)
1039*44704f69SBart Van Assche                 pr2serr("Unexpected extra argument: %s\n", argv[optind]);
1040*44704f69SBart Van Assche             usage();
1041*44704f69SBart Van Assche             return SG_LIB_SYNTAX_ERROR;
1042*44704f69SBart Van Assche         }
1043*44704f69SBart Van Assche     }
1044*44704f69SBart Van Assche #ifdef DEBUG
1045*44704f69SBart Van Assche     pr2serr("In DEBUG mode, ");
1046*44704f69SBart Van Assche     if (verbose_given && version_given) {
1047*44704f69SBart Van Assche         pr2serr("but override: '-vV' given, zero verbose and continue\n");
1048*44704f69SBart Van Assche         verbose_given = false;
1049*44704f69SBart Van Assche         version_given = false;
1050*44704f69SBart Van Assche         verbose = 0;
1051*44704f69SBart Van Assche     } else if (! verbose_given) {
1052*44704f69SBart Van Assche         pr2serr("set '-vv'\n");
1053*44704f69SBart Van Assche         verbose = 2;
1054*44704f69SBart Van Assche     } else
1055*44704f69SBart Van Assche         pr2serr("keep verbose=%d\n", verbose);
1056*44704f69SBart Van Assche #else
1057*44704f69SBart Van Assche     if (verbose_given && version_given)
1058*44704f69SBart Van Assche         pr2serr("Not in DEBUG mode, so '-vV' has no special action\n");
1059*44704f69SBart Van Assche #endif
1060*44704f69SBart Van Assche     if (version_given) {
1061*44704f69SBart Van Assche         pr2serr(ME "version: %s\n", version_str);
1062*44704f69SBart Van Assche         return 0;
1063*44704f69SBart Van Assche     }
1064*44704f69SBart Van Assche 
1065*44704f69SBart Van Assche     if (list) {
1066*44704f69SBart Van Assche         list_known(brief);
1067*44704f69SBart Van Assche         return 0;
1068*44704f69SBart Van Assche     }
1069*44704f69SBart Van Assche     if (NULL == device_name) {
1070*44704f69SBart Van Assche         pr2serr("missing device name!\n");
1071*44704f69SBart Van Assche         usage();
1072*44704f69SBart Van Assche         return SG_LIB_SYNTAX_ERROR;
1073*44704f69SBart Van Assche     }
1074*44704f69SBart Van Assche     if ((sg_fd = sg_cmds_open_device(device_name, true /* ro */, verbose))
1075*44704f69SBart Van Assche         < 0) {
1076*44704f69SBart Van Assche         pr2serr(ME "error opening file: %s (ro): %s\n", device_name,
1077*44704f69SBart Van Assche                 safe_strerror(-sg_fd));
1078*44704f69SBart Van Assche         return sg_convert_errno(-sg_fd);
1079*44704f69SBart Van Assche     }
1080*44704f69SBart Van Assche     if (0 == sg_simple_inquiry(sg_fd, &inq_resp, true, verbose)) {
1081*44704f69SBart Van Assche         if (! do_raw)
1082*44704f69SBart Van Assche             printf("  %.8s  %.16s  %.4s\n", inq_resp.vendor, inq_resp.product,
1083*44704f69SBart Van Assche                    inq_resp.revision);
1084*44704f69SBart Van Assche         peri_type = inq_resp.peripheral_type;
1085*44704f69SBart Van Assche         cp = sg_get_pdt_str(peri_type, sizeof(buff), buff);
1086*44704f69SBart Van Assche         if (! do_raw) {
1087*44704f69SBart Van Assche             if (strlen(cp) > 0)
1088*44704f69SBart Van Assche                 printf("  Peripheral device type: %s\n", cp);
1089*44704f69SBart Van Assche             else
1090*44704f69SBart Van Assche                 printf("  Peripheral device type: 0x%x\n", peri_type);
1091*44704f69SBart Van Assche         }
1092*44704f69SBart Van Assche     } else {
1093*44704f69SBart Van Assche         pr2serr(ME "%s doesn't respond to a SCSI INQUIRY\n", device_name);
1094*44704f69SBart Van Assche         return SG_LIB_CAT_OTHER;
1095*44704f69SBart Van Assche     }
1096*44704f69SBart Van Assche     sg_cmds_close_device(sg_fd);
1097*44704f69SBart Van Assche 
1098*44704f69SBart Van Assche     sg_fd = sg_cmds_open_device(device_name, readonly, verbose);
1099*44704f69SBart Van Assche     if (sg_fd < 0) {
1100*44704f69SBart Van Assche         pr2serr(ME "open error (rw): %s\n", safe_strerror(-sg_fd));
1101*44704f69SBart Van Assche         return sg_convert_errno(-sg_fd);
1102*44704f69SBart Van Assche     }
1103*44704f69SBart Van Assche     if (do_raw) {
1104*44704f69SBart Van Assche         if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
1105*44704f69SBart Van Assche             perror("sg_set_binary_mode");
1106*44704f69SBart Van Assche             return SG_LIB_FILE_ERROR;
1107*44704f69SBart Van Assche         }
1108*44704f69SBart Van Assche     }
1109*44704f69SBart Van Assche 
1110*44704f69SBart Van Assche     res = sg_ll_get_config(sg_fd, rt, starting, resp_buffer,
1111*44704f69SBart Van Assche                               sizeof(resp_buffer), true, verbose);
1112*44704f69SBart Van Assche     ret = res;
1113*44704f69SBart Van Assche     if (0 == res) {
1114*44704f69SBart Van Assche         len = sg_get_unaligned_be32(resp_buffer + 0) + 4;
1115*44704f69SBart Van Assche         if (do_hex) {
1116*44704f69SBart Van Assche             if (len > (int)sizeof(resp_buffer))
1117*44704f69SBart Van Assche                 len = sizeof(resp_buffer);
1118*44704f69SBart Van Assche             hex2stdout(resp_buffer, len, 0);
1119*44704f69SBart Van Assche         } else if (do_raw)
1120*44704f69SBart Van Assche             dStrRaw((const char *)resp_buffer, len);
1121*44704f69SBart Van Assche         else
1122*44704f69SBart Van Assche             decode_config(resp_buffer, sizeof(resp_buffer), len, brief,
1123*44704f69SBart Van Assche                           inner_hex);
1124*44704f69SBart Van Assche     } else {
1125*44704f69SBart Van Assche         char b[80];
1126*44704f69SBart Van Assche 
1127*44704f69SBart Van Assche         sg_get_category_sense_str(res, sizeof(b), b, verbose);
1128*44704f69SBart Van Assche         pr2serr("Get Configuration command: %s\n", b);
1129*44704f69SBart Van Assche         if (0 == verbose)
1130*44704f69SBart Van Assche             pr2serr("    try '-v' option for more information\n");
1131*44704f69SBart Van Assche     }
1132*44704f69SBart Van Assche 
1133*44704f69SBart Van Assche     res = sg_cmds_close_device(sg_fd);
1134*44704f69SBart Van Assche     if (res < 0) {
1135*44704f69SBart Van Assche         pr2serr("close error: %s\n", safe_strerror(-res));
1136*44704f69SBart Van Assche         if (0 == ret)
1137*44704f69SBart Van Assche             ret = sg_convert_errno(-ret);
1138*44704f69SBart Van Assche     }
1139*44704f69SBart Van Assche     if (0 == verbose) {
1140*44704f69SBart Van Assche         if (! sg_if_can2stderr("sg_get_config failed: ", ret))
1141*44704f69SBart Van Assche             pr2serr("Some error occurred, try again with '-v' or '-vv' for "
1142*44704f69SBart Van Assche                     "more information\n");
1143*44704f69SBart Van Assche     }
1144*44704f69SBart Van Assche     return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
1145*44704f69SBart Van Assche }
1146