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