aboutsummaryrefslogtreecommitdiff
path: root/examples/sg_simple5.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/sg_simple5.c')
-rw-r--r--examples/sg_simple5.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/examples/sg_simple5.c b/examples/sg_simple5.c
new file mode 100644
index 00000000..47bf7a05
--- /dev/null
+++ b/examples/sg_simple5.c
@@ -0,0 +1,236 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sg_lib.h"
+#include "sg_pt.h"
+
+/* This is a simple program executing a SCSI INQUIRY command and a
+ TEST UNIT READY command using the SCSI generic pass through
+ interface. This allows this example program to be ported to
+ OSes other than linux.
+
+* Copyright (C) 2006-20018 D. Gilbert
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2, or (at your option)
+* any later version.
+
+ Invocation: sg_simple5 [-x] <scsi_device>
+
+ Version 1.03 (20180220)
+
+*/
+
+#define INQ_REPLY_LEN 96
+#define INQ_CMD_LEN 6
+#define TUR_CMD_LEN 6
+
+#define CMD_TIMEOUT_SECS 60
+
+
+int main(int argc, char * argv[])
+{
+ int sg_fd, k, ok, dsize, res, duration, resid, cat, got, slen;
+ uint8_t inq_cdb [INQ_CMD_LEN] =
+ {0x12, 0, 0, 0, INQ_REPLY_LEN, 0};
+ uint8_t tur_cdb [TUR_CMD_LEN] =
+ {0x00, 0, 0, 0, 0, 0};
+ uint8_t inqBuff[INQ_REPLY_LEN];
+ char * file_name = 0;
+ char b[512];
+ uint8_t sense_b[32];
+ int verbose = 0;
+ struct sg_pt_base * ptvp;
+
+ for (k = 1; k < argc; ++k) {
+ if (0 == strcmp("-v", argv[k]))
+ verbose = 1;
+ else if (0 == strcmp("-vv", argv[k]))
+ verbose = 2;
+ else if (0 == strcmp("-vvv", argv[k]))
+ verbose = 3;
+ else if (*argv[k] == '-') {
+ printf("Unrecognized switch: %s\n", argv[k]);
+ file_name = 0;
+ break;
+ }
+ else if (0 == file_name)
+ file_name = argv[k];
+ else {
+ printf("too many arguments\n");
+ file_name = 0;
+ break;
+ }
+ }
+ if (0 == file_name) {
+ printf("Usage: 'sg_simple5 [-v|-vv|-vvv] <device>'\n");
+ return 1;
+ }
+
+ sg_fd = scsi_pt_open_device(file_name, 1 /* ro */, 0);
+ /* N.B. An access mode of O_RDWR is required for some SCSI commands */
+ if (sg_fd < 0) {
+ fprintf(stderr, "error opening file: %s: %s\n",
+ file_name, safe_strerror(-sg_fd));
+ return 1;
+ }
+
+ dsize = sizeof(inqBuff);
+ ok = 0;
+
+ ptvp = construct_scsi_pt_obj(); /* one object per command */
+ if (NULL == ptvp) {
+ fprintf(stderr, "sg_simple5: out of memory\n");
+ return -1;
+ }
+ set_scsi_pt_cdb(ptvp, inq_cdb, sizeof(inq_cdb));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ set_scsi_pt_data_in(ptvp, inqBuff, dsize);
+ res = do_scsi_pt(ptvp, sg_fd, CMD_TIMEOUT_SECS, verbose);
+ if (res < 0) {
+ fprintf(stderr, " pass through os error: %s\n",
+ safe_strerror(-res));
+ goto finish_inq;
+ } else if (SCSI_PT_DO_BAD_PARAMS == res) {
+ fprintf(stderr, " bad pass through setup\n");
+ goto finish_inq;
+ } else if (SCSI_PT_DO_TIMEOUT == res) {
+ fprintf(stderr, " pass through timeout\n");
+ goto finish_inq;
+ }
+ if ((verbose > 1) && ((duration = get_scsi_pt_duration_ms(ptvp)) >= 0))
+ fprintf(stderr, " duration=%d ms\n", duration);
+ resid = get_scsi_pt_resid(ptvp);
+ switch ((cat = get_scsi_pt_result_category(ptvp))) {
+ case SCSI_PT_RESULT_GOOD:
+ got = dsize - resid;
+ if (verbose && (resid > 0))
+ fprintf(stderr, " requested %d bytes but "
+ "got %d bytes)\n", dsize, got);
+ break;
+ case SCSI_PT_RESULT_STATUS: /* other than GOOD and CHECK CONDITION */
+ if (verbose) {
+ sg_get_scsi_status_str(get_scsi_pt_status_response(ptvp),
+ sizeof(b), b);
+ fprintf(stderr, " scsi status: %s\n", b);
+ }
+ goto finish_inq;
+ case SCSI_PT_RESULT_SENSE:
+ slen = get_scsi_pt_sense_len(ptvp);
+ if (verbose) {
+ sg_get_sense_str("", sense_b, slen, (verbose > 1),
+ sizeof(b), b);
+ fprintf(stderr, "%s", b);
+ }
+ if (verbose && (resid > 0)) {
+ got = dsize - resid;
+ if ((verbose) || (got > 0))
+ fprintf(stderr, " requested %d bytes but "
+ "got %d bytes\n", dsize, got);
+ }
+ goto finish_inq;
+ case SCSI_PT_RESULT_TRANSPORT_ERR:
+ if (verbose) {
+ get_scsi_pt_transport_err_str(ptvp, sizeof(b), b);
+ fprintf(stderr, " transport: %s", b);
+ }
+ goto finish_inq;
+ case SCSI_PT_RESULT_OS_ERR:
+ if (verbose) {
+ get_scsi_pt_os_err_str(ptvp, sizeof(b), b);
+ fprintf(stderr, " os: %s", b);
+ }
+ goto finish_inq;
+ default:
+ fprintf(stderr, " unknown pass through result "
+ "category (%d)\n", cat);
+ goto finish_inq;
+ }
+
+ ok = 1;
+finish_inq:
+ destruct_scsi_pt_obj(ptvp);
+
+ if (ok) { /* output result if it is available */
+ char * p = (char *)inqBuff;
+
+ printf("Some of the INQUIRY command's results:\n");
+ printf(" %.8s %.16s %.4s\n", p + 8, p + 16, p + 32);
+ }
+ ok = 0;
+
+
+ /* Now prepare TEST UNIT READY command */
+ ptvp = construct_scsi_pt_obj(); /* one object per command */
+ if (NULL == ptvp) {
+ fprintf(stderr, "sg_simple5: out of memory\n");
+ return -1;
+ }
+ set_scsi_pt_cdb(ptvp, tur_cdb, sizeof(tur_cdb));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ /* no data in or out */
+ res = do_scsi_pt(ptvp, sg_fd, CMD_TIMEOUT_SECS, verbose);
+ if (res < 0) {
+ fprintf(stderr, " pass through os error: %s\n",
+ safe_strerror(-res));
+ goto finish_inq;
+ } else if (SCSI_PT_DO_BAD_PARAMS == res) {
+ fprintf(stderr, " bad pass through setup\n");
+ goto finish_inq;
+ } else if (SCSI_PT_DO_TIMEOUT == res) {
+ fprintf(stderr, " pass through timeout\n");
+ goto finish_inq;
+ }
+ if ((verbose > 1) && ((duration = get_scsi_pt_duration_ms(ptvp)) >= 0))
+ fprintf(stderr, " duration=%d ms\n", duration);
+ resid = get_scsi_pt_resid(ptvp);
+ switch ((cat = get_scsi_pt_result_category(ptvp))) {
+ case SCSI_PT_RESULT_GOOD:
+ break;
+ case SCSI_PT_RESULT_STATUS: /* other than GOOD and CHECK CONDITION */
+ if (verbose) {
+ sg_get_scsi_status_str(get_scsi_pt_status_response(ptvp),
+ sizeof(b), b);
+ fprintf(stderr, " scsi status: %s\n", b);
+ }
+ goto finish_tur;
+ case SCSI_PT_RESULT_SENSE:
+ slen = get_scsi_pt_sense_len(ptvp);
+ if (verbose) {
+ sg_get_sense_str("", sense_b, slen, (verbose > 1),
+ sizeof(b), b);
+ fprintf(stderr, "%s", b);
+ }
+ goto finish_tur;
+ case SCSI_PT_RESULT_TRANSPORT_ERR:
+ if (verbose) {
+ get_scsi_pt_transport_err_str(ptvp, sizeof(b), b);
+ fprintf(stderr, " transport: %s", b);
+ }
+ goto finish_tur;
+ case SCSI_PT_RESULT_OS_ERR:
+ if (verbose) {
+ get_scsi_pt_os_err_str(ptvp, sizeof(b), b);
+ fprintf(stderr, " os: %s", b);
+ }
+ goto finish_tur;
+ default:
+ fprintf(stderr, " unknown pass through result "
+ "category (%d)\n", cat);
+ goto finish_tur;
+ }
+
+ ok = 1;
+finish_tur:
+ destruct_scsi_pt_obj(ptvp);
+
+ if (ok)
+ printf("Test Unit Ready successful so unit is ready!\n");
+ else
+ printf("Test Unit Ready failed so unit may _not_ be ready!\n");
+
+ scsi_pt_close_device(sg_fd);
+ return 0;
+}