Page suivante Page précédente - Table des matières

24. Programmes d'exemple

Voici le programme exemple en C qui demande le constructeur et le modèle et indique si un medium est chargé dans le périphérique.

#define DEVICE "/dev/sgc"
/* Programme de demonstration de l'interface SCSI generique */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <scsi/sg.h>
#define SCSI_OFF sizeof(struct sg_header)
static unsigned char cmd[SCSI_OFF + 18];        /* tampon de commandes SCSI */
int     fd;                          /* descripteur de periph./fichier SCSI */
/* traite une commande SCSI complete. Utilise l'interface SCSI generique */
static int handle_scsi_cmd(unsigned cmd_len,         /* longueur */
 unsigned in_size,         /* taille data IN */
 unsigned char *i_buff,    /* tampon IN */
 unsigned out_size,        /* taille data OUT */
 unsigned char *o_buff     /* tampon OUT */
 )
{
 int status = 0;
 struct sg_header *sg_hd;
 /* quelques controles de routine */
 if (!cmd_len) return -1;            /* cmd_len doit etre != 0 */
 if (!i_buff) return -1;             /* tampon IN doit etre != NULL */
#ifdef SG_BIG_BUFF
 if (SCSI_OFF + cmd_len + in_size> SG_BIG_BUFF) return -1;
 if (SCSI_OFF + out_size> SG_BIG_BUFF) return -1;
#else
 if (SCSI_OFF + cmd_len + in_size> 4096) return -1;
 if (SCSI_OFF + out_size> 4096) return -1;
#endif
 if (!o_buff) out_size = 0;
 /* construction de l'en-tete du pilote generique */
 sg_hd = (struct sg_header *) i_buff;
 sg_hd->reply_len   = SCSI_OFF + out_size;
 sg_hd->twelve_byte = cmd_len == 12;
 sg_hd->result = 0;
#if     0
 sg_hd->pack_len    = SCSI_OFF + cmd_len + in_size; /* pas indispensable */
 sg_hd->pack_id;     /* inutilise */
 sg_hd->other_flags; /* inutilise */
#endif
 /* envoi de la commande */
 status = write( fd, i_buff, SCSI_OFF + cmd_len + in_size );
 if ( status < 0 || status != SCSI_OFF + cmd_len + in_size ||
 sg_hd->result ) {
 /* une erreur s'est produite */
 fprintf( stderr, "ecriture (generique) resultat = 0x%x cmd = 0x%x\n",
 sg_hd->result, i_buff[SCSI_OFF] );
 perror("");
 return status;
 }
 if (!o_buff) o_buff = i_buff;       /* controle du pointeur du tampon */
 /* recuperation du resultat */
 status = read( fd, o_buff, SCSI_OFF + out_size);
 if ( status < 0 || status != SCSI_OFF + out_size || sg_hd->result ) {
 /* une erreur s'est produite */
 fprintf( stderr, "lecture (generique) resultat = 0x%x cmd = 0x%x\n",
 sg_hd->result, o_buff[SCSI_OFF] );
 fprintf( stderr, "read(generic) sense "
 "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
 sg_hd->sense_buffer[0],         sg_hd->sense_buffer[1],
 sg_hd->sense_buffer[2],         sg_hd->sense_buffer[3],
 sg_hd->sense_buffer[4],         sg_hd->sense_buffer[5],
 sg_hd->sense_buffer[6],         sg_hd->sense_buffer[7],
 sg_hd->sense_buffer[8],         sg_hd->sense_buffer[9],
 sg_hd->sense_buffer[10],        sg_hd->sense_buffer[11],
 sg_hd->sense_buffer[12],        sg_hd->sense_buffer[13],
 sg_hd->sense_buffer[14],        sg_hd->sense_buffer[15]);
 if (status < 0)
 perror("");
 }
 /* Voyons si nous avons ce que nous attendions */
 if (status == SCSI_OFF + out_size) status = 0; /* on a tout */
 return status;  /* 0 indique que tout est OK */
}
#define INQUIRY_CMD     0x12
#define INQUIRY_CMDLEN  6
#define INQUIRY_REPLY_LEN 96
#define INQUIRY_VENDOR  8    /* Decalage sur le constructeur dans la reponse */
/* On demande le constructeur et le modele */
static unsigned char *Inquiry ( void )
{
 unsigned char Inqbuffer[ SCSI_OFF + INQUIRY_REPLY_LEN ];
 unsigned char cmdblk [ INQUIRY_CMDLEN ] =
 { INQUIRY_CMD,  /* commande */
 0,  /* lun/reserve */
 0,  /* code page */
 0,  /* reserve */
 INQUIRY_REPLY_LEN,  /* longueur d'allocation */
 0 };/* reserve/drapeau/lien */
 memcpy( cmd + SCSI_OFF, cmdblk, sizeof(cmdblk) );
 /*
 * +------------------+
 * | struct sg_header | <- cmd
 * +------------------+
 * | copie de cmdblk  | <- cmd + SCSI_OFF
 * +------------------+
 */
 if (handle_scsi_cmd(sizeof(cmdblk), 0, cmd,
 sizeof(Inqbuffer) - SCSI_OFF, Inqbuffer )) {
 fprintf( stderr, "Echec de la demande\n" );
 exit(2);
 }
 return (Inqbuffer + SCSI_OFF);
}
#define TESTUNITREADY_CMD 0
#define TESTUNITREADY_CMDLEN 6
#define ADD_SENSECODE 12
#define ADD_SC_QUALIFIER 13
#define NO_MEDIA_SC 0x3a
#define NO_MEDIA_SCQ 0x00
int TestForMedium ( void )
{
 /* demande de l'etat READY */
 static unsigned char cmdblk [TESTUNITREADY_CMDLEN] = {
 TESTUNITREADY_CMD, /* commande */
 0, /* lun/reserve */
 0, /* reserve */
 0, /* reserve */
 0, /* reserve */
 0};/* reserve */
 memcpy( cmd + SCSI_OFF, cmdblk, sizeof(cmdblk) );
 /*
 * +------------------+
 * | struct sg_header | <- cmd
 * +------------------+
 * | copie de cmdblk  | <- cmd + SCSI_OFF
 * +------------------+
 */
 if (handle_scsi_cmd(sizeof(cmdblk), 0, cmd,
 0, NULL)) {
 fprintf (stderr, "Echec du test d'unite prete\n");
 exit(2);
 }
 return
 *(((struct sg_header*)cmd)->sense_buffer +ADD_SENSECODE) !=
 NO_MEDIA_SC ||
 *(((struct sg_header*)cmd)->sense_buffer +ADD_SC_QUALIFIER) !=
 NO_MEDIA_SCQ;
}
void main( void )
{
 fd = open(DEVICE, O_RDWR);
 if (fd < 0) {
 fprintf( stderr, "Il faut les droits lecture/ecriture sur "DEVICE".\n" );
 exit(1);
 }
 /* on ecrit quelques champs du resultat de la requete */
 printf( "%s\n", Inquiry() + INQUIRY_VENDOR );
 /* on regarde si le medium est charge */
 if (!TestForMedium()) {
 printf("pas de medium charge\n");
 } else {
 printf("un medium est present\n");
 }
}


Page suivante Page précédente - Table des matières