xref: /aosp_15_r20/external/sg3_utils/examples/sg_simple16.c (revision 44704f698541f6367e81f991ef8bb54ccbf3fc18)
1 #include <unistd.h>
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <stdint.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <sys/ioctl.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include "sg_lib.h"
12 #include "sg_io_linux.h"
13 
14 /* This program performs a READ_16 command as scsi mid-level support
15    16 byte commands from lk 2.4.15
16 
17 *  Copyright (C) 2001-2018 D. Gilbert
18 *  This program is free software; you can redistribute it and/or modify
19 *  it under the terms of the GNU General Public License as published by
20 *  the Free Software Foundation; either version 2, or (at your option)
21 *  any later version.
22 
23    Invocation: sg_simple16 <scsi_device>
24 
25    Version 1.04 (20180218)
26 
27 */
28 
29 #define READ16_REPLY_LEN 512
30 #define READ16_CMD_LEN 16
31 
32 #define EBUFF_SZ 256
33 
main(int argc,char * argv[])34 int main(int argc, char * argv[])
35 {
36     int sg_fd, k, ok;
37     uint8_t r16_cdb [READ16_CMD_LEN] =
38                 {0x88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0};
39     sg_io_hdr_t io_hdr;
40     char * file_name = 0;
41     char ebuff[EBUFF_SZ];
42     uint8_t inBuff[READ16_REPLY_LEN];
43     uint8_t sense_buffer[32];
44 
45     for (k = 1; k < argc; ++k) {
46         if (*argv[k] == '-') {
47             printf("Unrecognized switch: %s\n", argv[k]);
48             file_name = 0;
49             break;
50         }
51         else if (0 == file_name)
52             file_name = argv[k];
53         else {
54             printf("too many arguments\n");
55             file_name = 0;
56             break;
57         }
58     }
59     if (0 == file_name) {
60         printf("Usage: 'sg_simple16 <sg_device>'\n");
61         return 1;
62     }
63 
64     if ((sg_fd = open(file_name, O_RDWR)) < 0) {
65         snprintf(ebuff, EBUFF_SZ,
66                  "sg_simple16: error opening file: %s", file_name);
67         perror(ebuff);
68         return 1;
69     }
70     /* Just to be safe, check we have a new sg device by trying an ioctl */
71     if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
72         printf("sg_simple16: %s doesn't seem to be an new sg device\n",
73                file_name);
74         close(sg_fd);
75         return 1;
76     }
77 
78     /* Prepare READ_16 command */
79     memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
80     io_hdr.interface_id = 'S';
81     io_hdr.cmd_len = sizeof(r16_cdb);
82     /* io_hdr.iovec_count = 0; */  /* memset takes care of this */
83     io_hdr.mx_sb_len = sizeof(sense_buffer);
84     io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
85     io_hdr.dxfer_len = READ16_REPLY_LEN;
86     io_hdr.dxferp = inBuff;
87     io_hdr.cmdp = r16_cdb;
88     io_hdr.sbp = sense_buffer;
89     io_hdr.timeout = 20000;     /* 20000 millisecs == 20 seconds */
90     /* io_hdr.flags = 0; */     /* take defaults: indirect IO, etc */
91     /* io_hdr.pack_id = 0; */
92     /* io_hdr.usr_ptr = NULL; */
93 
94     if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
95         perror("sg_simple16: Inquiry SG_IO ioctl error");
96         close(sg_fd);
97         return 1;
98     }
99 
100     /* now for the error processing */
101     ok = 0;
102     switch (sg_err_category3(&io_hdr)) {
103     case SG_LIB_CAT_CLEAN:
104         ok = 1;
105         break;
106     case SG_LIB_CAT_RECOVERED:
107         printf("Recovered error on READ_16, continuing\n");
108         ok = 1;
109         break;
110     default: /* won't bother decoding other categories */
111         sg_chk_n_print3("READ_16 command error", &io_hdr, 1);
112         break;
113     }
114 
115     if (ok) { /* output result if it is available */
116         printf("READ_16 duration=%u millisecs, resid=%d, msg_status=%d\n",
117                io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status);
118     }
119 
120     close(sg_fd);
121     return 0;
122 }
123