Example: Using the control device (QTACTLDV) API

This example shows how the QTACTLDV (Control Device) API could be used to send a diagnostic command to a tape device.

Note: Read the Code license and disclaimer information for important legal information.
/* Usage example 1 for QTACTLDV API                                 */
/*                                                                  */
/*                                                                  */

 #include <string.h>
 #include <stdio.h>
 #include <qtactldv.h>
 #include <qusec.h>

 /********************************************************************/
 /*  Typedef structure for QTACTLDV                                  */
 /********************************************************************/
 typedef struct {                          /* QTACTLDV command data  */
   Qta_CTLD0100_t  data;                   /*   command data         */
   char        cmd_str[6];                 /*   command string       */
 } cmd_struct;

 /********************************************************************/
 /*  Typedef structure for Error code                                */
 /********************************************************************/
 typedef struct {                          /* Error code structure   */
   Qus_EC_t    Edata;                      /*   Error code data      */
                                           /* CPF67C8 excp data      */
   char        dev_nam[10];                /*   Device name          */
   char        reason_cd[3];               /*   Reason code          */
   char        resv1[3];                   /*   Reserved             */
 } EC_struct;

 /********************************************************************/
 /*  Constants                                                       */
 /********************************************************************/

 #define  SNDRSNS "\x03\x00\x00\x00\x12\x00"  /* Request sense       */
                                              /* command string      */
 #define  SNDDIAG "\x1D\x04\x00\x00\x00\x00"  /* Send diagnostic     */
                                              /* command string      */


 main(int argc,char *argv[])
 {
 /********************************************************************/
 /*                                                                  */
 /*  START OF MAINLINE                                               */
 /*                                                                  */
 /********************************************************************/

 /********************************************************************/
 /*  Variables for QTACTLDV                                          */
 /********************************************************************/
  char                  device[10];        /* device name            */
  char                  send_buff[256];    /* send buffer            */
  int                   send_buff_len;     /* length of send buffer  */
  char                  recv_buff[256];    /* receive buffer         */
  int                   recv_buff_len;     /* length of recv buffer  */
  int                   cmd_data_len;      /* length of command data */
  int                   i;                 /* counter variable       */

  EC_struct             EC;                /* error code structure   */
  cmd_struct            Cmd;               /* struct for QTACTLDV    */

  memcpy(device,argv[1],10);               /* copy device name       */

 /********************************************************************/
 /*  OPEN connection                                                 */
 /********************************************************************/
  send_buff_len = 0;                       /* no send buffer         */
  recv_buff_len = 0;                       /* no receive buffer      */
  cmd_data_len = 0;                        /* no command data        */
  EC.Edata.Bytes_Provided = 32;            /* No exceptions          */

  QTACTLDV(device,                       /* device name              */
           FUNOPEN,                      /* requested function       */
           send_buff,                    /* send buffer              */
           send_buff_len,                /* length of send buffer    */
           recv_buff,                    /* receive buffer           */
           recv_buff_len,                /* length of receive buffer */
           CTLD0100,                     /* command format           */
           &Cmd,                         /* command data             */
           cmd_data_len,                 /* length of command data   */
           &EC);                         /* Error Code               */

 if (EC.Edata.Bytes_Available>0)   /* If there was an error          */
 {
   /* Handle the error                                               */
 }

 /********************************************************************/
 /*  Send Diagnostic command                                         */
 /********************************************************************/
  send_buff_len = 0;                       /* no send buffer         */
  recv_buff_len = 0;                       /* no recv buffer         */
  cmd_data_len = sizeof(Cmd);              /* size of command struct */
  EC.Edata.Bytes_Provided = 32;            /* No exceptions          */
  Cmd.data.Data_transfer_direction = XFRNONE;  /* No data transfer   */
  Cmd.data.Requested_transfer_length = 0;      /* 0 transfer length  */
  Cmd.data.Ignore_length_errors = RPTLERR;     /* report length errs */
  Cmd.data.Command_timeout = 600;              /* 10 minute timeout  */
  Cmd.data.Type_of_command = CMDSCSI;          /* SCSI command       */
  Cmd.data.Offset_to_command_string = 32;      /* offset 32          */
  Cmd.data.Length_of_command_string = 6;       /* 6 byte command     */
  Cmd.data.Reserved1=0;                        /* reserved           */
  memcpy(&Cmd.cmd_str, SNDDIAG, 6);            /* command string     */

  QTACTLDV(device,                 /* device name                    */
           FUNCMD,                 /* requested function             */
           send_buff,              /* send buffer                    */
           send_buff_len,          /* length of send buffer          */
           recv_buff,              /* receive buffer                 */
           recv_buff_len,          /* length of receive buffer       */
           CTLD0100,               /* command format                 */
           &Cmd,                   /* command data                   */
           cmd_data_len,           /* length of command data         */
           &EC);                   /* Error code                     */

 if (EC.Edata.Bytes_Available>0)   /* If there was an error          */
 {
   /* See what message was returned                                  */
   if (strncmp(EC.Edata.Exception_Id,"CPF67C8",7)==0) /* Command
                                                         failed msg  */
   {
     /****************************************************************/
     /* Check the data returned with CPF67C8                         */
     /****************************************************************/

     if (strncmp(EC.reason_cd,"\x02\xC0", 2) == 0) /* Device detected
                                                             error   */
     {
       /* Check the SCSI completion status                           */
       if (EC.reason_cd[2]=='\x02')      /* Check condition status   */
       {
         /************************************************************/
         /*  Send Request Sense command                              */
         /************************************************************/
         send_buff_len = 0;               /* no send buffer          */
         recv_buff_len = 18;              /* length of recv buffer   */
         cmd_data_len = sizeof(Cmd);      /* size of command struct  */
         Cmd.data.Data_transfer_direction = XFRRECV; /* receive      */
         Cmd.data.Requested_transfer_length = 18;    /* 18 bytes     */
         Cmd.data.Ignore_length_errors = IGNLERR; /* ignore length
                                                            errors   */
         Cmd.data.Command_timeout = 60;          /* 60 sec timeout   */
         Cmd.data.Type_of_command = CMDSCSI;     /* SCSI command     */
         Cmd.data.Offset_to_command_string = 32; /* offset 32        */
         Cmd.data.Length_of_command_string = 6;  /* 6 byte cmd       */
         Cmd.data.Reserved1=0;                 /* reserved           */
         memcpy(&Cmd.cmd_str, SNDRSNS, 6);       /* command string   */

         EC.Edata.Bytes_Provided = 32;    /* No exceptions           */

         QTACTLDV(device,         /* device name                     */
                  FUNCMD,         /* requested function              */
                  send_buff,      /* send buffer                     */
                  send_buff_len,  /* length of send buffer           */
                  recv_buff,      /* receive buffer                  */
                  recv_buff_len,  /* length of receive buffer        */
                  CTLD0100,       /* command format                  */
                  &Cmd,           /* command data                    */
                  cmd_data_len,   /* length of command data          */
                  &EC);           /* Error code                      */

         if (EC.Edata.Bytes_Available>0)   /* If there was an error  */
         {
           /* Handle error on request sense command                  */
         }
         else
         {
           /* Parse the request sense data to determine what action  */
           /* to take.                                               */
         }
       }
       else if (EC.reason_cd[2]=='\x08')  /* Busy status             */
       {
         /* Try the command again later                              */
       }
       else                       /* Unexpected completion status    */
       {
         /* Send error message for unexpected completion status      */
       }
     }

     else if (strncmp(EC.reason_cd,"\x02\xC1\x00", 3) == 0)
                                            /* Selection timeout     */
     {
       /* Send message that device might be powered off              */
     }

     /* Add else if for the other reason codes here                  */

     else
     {
       /* Send error message for unexpected reason code              */
     }
   }

   else
   {
     /* Handle other messages                                        */
   }
 }
 else
 {
   /* No error                                                       */
 }

 /********************************************************************/
 /*  CLOSE connection                                                */
 /********************************************************************/
  send_buff_len = 0;                       /* no send buffer         */
  recv_buff_len = 0;                       /* no receive buffer      */
  cmd_data_len = 0;                        /* no command data        */
  EC.Edata.Bytes_Provided = 32;            /* No exceptions          */

  QTACTLDV(device,                       /* device name              */
           FUNCLOS,                      /* requested function       */
           send_buff,                    /* send buffer              */
           send_buff_len,                /* length of send buffer    */
           recv_buff,                    /* receive buffer           */
           recv_buff_len,                /* length of receive buffer */
           CTLD0100,                     /* command format           */
           &Cmd,                         /* command data             */
           cmd_data_len,                 /* length of command data   */
           &EC.Edata);                   /* Error code               */

 if (EC.Edata.Bytes_Available>0)   /* If there was an error          */
 {
   /* Handle the error                                               */
 }

 }

This example shows how the QTACTLDV (Control Device) API could be used to display the tape device firmware level.

/* Usage example 2 for QTACTLDV API                                 */
/*                                                                  */
/*                                                                  */

#include                     // Control Device API
#include                        // Error code header
#include                       // String Header File
#include                        // Standard I/O Header
#include                       // Standard Library Header
#include                       // Exception & cancel declares

/*********************************************************************/
/* Type definitions                                                  */
/*********************************************************************/
// Define the command structure for sending commands using QTACTLDV API.
typedef struct {                                 // Command Structure
  Qta_CTLD0100_t      hdr;                       // Header
  char                cmd_str[6];                // Command String
} ctldv_cmd_t;

/**********************************************************************/
/* Entry point to program.                                            */
/**********************************************************************/
int main (int argc, char *argv[])
{
  char                device[10];        // Device name to get FM level
  int                 deviceLen;         // Length of device name to cop
  char                send_buff[1];      // Send buffer
  int                 send_buff_len;     // Length of send buffer
  char                recv_buff[50];     // Receive buffer
  int                 recv_buff_len;     // Length of receive buffer
  ctldv_cmd_t         ctldv_cmd;         // Command variable
  int                 ctldv_cmd_len;     // Length of command string
  char                tempChar;          // Used to conver ASCII to EBCD
  Qus_EC_t            EC;                // Error code for qtactldv
  char                code[4];           // EBCDIC code level
  int                 i;                 // Iterator to move ASCII to EB

  EC.Bytes_Provided = 0;                        // Return errors to user
  memset(device, ' ', sizeof(device));          // Set to blanks
  deviceLen=strlen(argv[1]);
  if (deviceLen>10)
    deviceLen=10;
  memcpy(device, argv[1], deviceLen);           // Copy up to 10 chars

  memset(code, ' ', sizeof(code));              // Clear code level

  /********************************************************************/
  /* Open the pipe.                                                   */
  /********************************************************************/
  send_buff_len = 0;                             // No send buffer
  recv_buff_len = 0;                             // No receive buffer
  ctldv_cmd_len = 0;                             // No command

  #pragma exception_handler(PipeFailed, 0, 0, _C2_MH_ESCAPE, _CTLA_HANDLE)
  QTACTLDV(device,                              // Device name
           FUNOPEN,                             // Function requested
           send_buff,                           // Send buffer
           send_buff_len,                       // Send buffer length
           recv_buff,                           // Receive buffer
           recv_buff_len,                       // Receive buffer length
           CTLD0100,                            // Command structure
           &cldv_cmd,                           // Command data
           ctldv_cmd_len,                       // Command data length
           &EC);                                // Error structure
  #pragma disable_handler

  /********************************************************************/
  /* Get the drive VPD                                                */
  /********************************************************************/
  recv_buff_len = 16;                          // Receive buffer for VPD
  send_buff_len = 0;                           // No send buffer
  ctldv_cmd_len = 32 + 6;                      // Reserve command size
  ctldv_cmd.hdr.Command_timeout = 600;         // 10 minute timeout
  ctldv_cmd.hdr.Type_of_command = 0;           // SCSI Command
  ctldv_cmd.hdr.Offset_to_command_string = sizeof(ctldv_cmd.hdr); // Offset 32
  ctldv_cmd.hdr.Length_of_command_string = 6;    // 6 byte command
  ctldv_cmd.hdr.Reserved1 = 0;                   // Reserved
  ctldv_cmd.hdr.Data_transfer_direction=XFRRECV; // Receiving inquiry data
  ctldv_cmd.hdr.Requested_transfer_length=16;    // Number of bytes to transfer
  ctldv_cmd.hdr.Ignore_length_errors = RPTLERR;  // Report length errors
  memset(ctldv_cmd.cmd_str, 0x00, 6);            // clear command
  ctldv_cmd.cmd_str[0] = 0x12;                   // set to Inquiry command
  ctldv_cmd.cmd_str[1] = 0x01;                   // set EVPD mode
  ctldv_cmd.cmd_str[2] = 0x03;                   // Set code page - VPD
  ctldv_cmd.cmd_str[4] = 0x10;                   // Allocation length

  #pragma exception_handler(PipeClose, 0, 0, _C2_MH_ESCAPE, _CTLA_HANDLE)
  QTACTLDV(device,                               // Device name
           FUNCMD,                               // Function requested
           send_buff,                            // Send buffer
           send_buff_len,                        // Send buffer length
           recv_buff,                            // Receive buffer
           recv_buff_len,                        // Receive buffer length
           CTLD0100,                             // Command structure
           &cldv_cmd,                           // Command data
           ctldv_cmd_len,                        // Command data length
           &EC);                                 // Error structure
  #pragma disable_handler

  /********************************************************************/
  /* Convert the level to EBSDIC                                      */
  /********************************************************************/
  for (i = 0; (i < sizeof(code)); i++)
  {
     tempChar = recv_buff[12+i];              // Code offest in VPD data
     if (tempChar < 0x41)                     // is it a number?
       tempChar = tempChar - 0x30 + 0xF0;     // ASCII to EBCDII 0-9
     else {
       tempChar = tempChar & 0xDF;         // Convert to ASCII uppercase
       if (tempChar < 0x4A)                // is char < J ?
	 tempChar = tempChar - 0x41 + 0xC1;      // ASCII to EBCDII A-I
       else if (tempChar < 0x53)                 // is char < S
	 tempChar = tempChar - 0x4A + 0xD1;      // ASCII to EBCDII J-R
       else
	 tempChar = tempChar - 0x53 + 0xE2;      // ASCII to EBCDII S-Z
     }
     code[i] = tempChar;                        // Output the EBCDIC char
  }
  printf("The code level is: %s\n", code);

  /*********************************************************************/
  /*  Close the pipe.                                                  */
  /*********************************************************************/
  PipeClose:
  send_buff_len = 0;                             // No send buffer
  recv_buff_len = 0;                             // No receive buffer
  ctldv_cmd_len = 0;                             // No command

  #pragma exception_handler(PipeFailed, 0, 0, _C2_MH_ESCAPE, _CTLA_HANDLE)
  QTACTLDV(device,                               // Device name
           FUNCLOS,                              // Function requested
           send_buff,                            // Send buffer
           send_buff_len,                        // Send buffer length
           recv_buff,                            // Receive buffer
           recv_buff_len,                        // Receive buffer length
           CTLD0100,                             // Command structure
           &cldv_cmd,                           // Command data
           ctldv_cmd_len,                        // Command data length
           &EC);                                 // Error structure
  #pragma disable_handler

  PipeFailed:
  return 0;                                      // return to user
}