/*
* Get's the status of the drive through the GET EVENT / STATUS
* NOTIFICATION command.
*
* Requires a patched 2.2 kernel or 2.3.14 and newer - get the patch from
* www.kernel.dk. Just grab the newest one.
*
*
* Jens Axboe, 1999
* Adjusted by Erik Andersen
*/
#include
#include
#include
#include
#include
#include
/* if we don't have one, we have neither */
#ifndef GPCMD_INQUIRY
#define GPCMD_INQUIRY 0x12
#define GPCMD_GET_CONFIGURATION 0x46
#defined GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
#endif
int do_get_configuration(int fd);
int do_event_status(int fd);
int main(int argc, char **argv)
{
char *program;
char device[80];
int fd, remov_media, i, k;
char buffer[4096];
struct cdrom_generic_command cgc;
long datalength;
long temp;
program = argv[0];
++argv;
--argc;
if (argv[0] == 0 )
strcpy(device, "/dev/cdrom" );
else if (strcmp (argv[0], "-v") == 0) {
fprintf (stderr, "usage: %s \n", program);
exit (1);
}
else
strncpy(device, argv[0], 80);
fd = open(device, O_RDONLY|O_NONBLOCK);
if (fd == -1) {
perror("open");
return 1;
}
/* First do an INQUIRY -- find out what we have */
memset(&cgc, 0, sizeof(cgc));
memset(buffer, 0, sizeof(buffer));
cgc.cmd[0] = GPCMD_INQUIRY;
cgc.cmd[4] = cgc.buflen = 36;
memcpy(buffer, &cgc, sizeof(cgc));
if (ioctl(fd, CDROM_SEND_PACKET, buffer) < 0) {
perror("GPCMD_INQUIRY");
return 1;
}
for (i=8;i<15;i++)
if (buffer[i]==' '&&buffer[i+1]==' ') buffer[i]='\0';
if (buffer[15]==' ') buffer[15]='\0';
for (i=16;i<32;i++)
if (buffer[i]==' '&&buffer[i+1]==' ') buffer[i]='\0';
if (buffer[31]==' ') buffer[31]='\0';
printf("Drive: %.8s %.16s\n", &buffer[8], &buffer[16]);
printf("peripheral type=");
switch (buffer[0] & 0x3f) {
case 0: printf("hard drive\n");break;
case 5: printf("CD/DVD drive\n");break;
case 7: printf("Optical memory\n");break;
case 0x1f: printf("Unknown or none\n");break;
default: printf("This shouldn't happen!\n");
}
remov_media=(buffer[1] & 0x80)? 1 : 0;
printf("Removable media?=%s\n", remov_media? "Yes" : "No");
printf("Interface Type=%s\n", ((buffer[2]&0xc0)==0)? "ATAPI":"SCSI");
printf("ATAPI version=");
switch ((buffer[3] & 0xf0)>>4) {
case 0: printf("ATAPI ??0??\n");break;
case 1: printf("ATAPI ??1??\n");break;
case 2: printf("ATAPI 2.6\n");break;
case 3: printf("Mt. Fuji (cool!)\n");break;
default: printf("Unknown -- %x\n", (buffer[3] & 0xf0)>>4);break;
}
buffer[3] = 3 << 4;
if ((buffer[3] & 0xf0)>>4 == 3)
printf("drive supports Mt. Fuji\n");
else
return 0;
/* drive supports Mt. Fuji */
if ( (buffer[3] & 0xf0)>>4 == 3) {
printf("-- testing GET_CONFIGURATION:\n");
i=do_get_configuration(fd);
if(i!=0)
return i;
}
if ( (buffer[3] & 0xf0)>>4 == 3) {
printf("-- testing GET_EVENT_STATUS_NOTIFICATION:\n");
i=do_event_status(fd);
if(i!=0)
return i;
}
return 0;
}
int do_get_configuration(int fd)
{
char *program;
char device[80];
int remov_media, i, k;
char buffer[4096];
struct cdrom_generic_command cgc;
long datalength;
long temp;
/* Now do a GET_CONFIGURATION -- poke and prod for details */
/* First, just get the header to find size */
memset(&cgc, 0, sizeof(cgc));
memset(buffer, 0, sizeof(buffer));
cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
cgc.cmd[8] = cgc.buflen = 8;
memcpy(buffer, &cgc, sizeof(cgc));
if (ioctl(fd, CDROM_SEND_PACKET, buffer) < 0) {
if (errno == EIO) {
printf("Profiles not supported\n");
return 0;
}
perror("GPCMD_GET_CONFIGURATION header");
return 1;
}
/* get the rest since we know the size now */
memset(&cgc, 0, sizeof(cgc));
cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
cgc.cmd[8] = cgc.buflen = buffer[3] | (buffer[2] << 8);
memset(buffer, 0, sizeof(buffer));
memcpy(buffer, &cgc, sizeof(cgc));
if (ioctl(fd, CDROM_SEND_PACKET, buffer) < 0) {
perror("GPCMD_GET_CONFIGURATION");
return 1;
}
datalength = buffer[3] | (buffer[2] << 8) | (buffer[1] << 16) |
(buffer[0] << 24);
printf("------------------------\n");
printf("Current device profile=");
switch (buffer[7] | (buffer[6] << 8)) {
case 1: printf("hard drive\n");break;
case 2: printf("hard drive w/rem. media\n");break;
case 8: printf("CD-ROM drive\n");break;
case 9: printf("CD-R drive\n");break;
case 0xa: printf("CD-RW drive\n");break;
case 0x10: printf("DVD-ROM drive\n");break;
case 0x11: printf("DVD-R drive\n");break;
case 0x12: printf("DVD-RAM drive\n");break;
default: printf("Something else!\n");
}
for (k=8; k>1)? "Yes" : "No" );
//printf("Version=%d\n", buffer[k+2]&0x3c>>2 );
//printf("Additional Length=%d\n", buffer[k+3] );
k+=(buffer[k+3])+4;
}
printf("------------------------\n");
return 0;
}
/* Not working properly yet... */
/* buggy! */
int do_event_status(int fd)
{
char *program;
char device[80];
int remov_media, i, k;
char buffer[4096];
struct cdrom_generic_command cgc;
long datalength;
long temp;
/* Now do a GET_EVENT_STATUS_NOTIFICATION */
memset(&cgc, 0, sizeof(cgc));
memset(buffer, 0, sizeof(buffer));
cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
cgc.cmd[1] = 1;
cgc.cmd[4] = 16;
cgc.cmd[8] = cgc.buflen = 8;
memcpy(buffer, &cgc, sizeof(cgc));
if (ioctl(fd, CDROM_SEND_PACKET, buffer) < 0) {
if (errno == EIO) {
printf("Event notification not supported\n");
return 0;
}
perror("GPCMD_GET_EVENT_STATUS_NOTIFICATION");
return 1;
}
/* list supported notification classes */
printf("event classes supported by this drive :\n");
if (buffer[3] & 2)
printf("\toperational change request/notification\n");
if (buffer[3] & 4)
printf("\tpower management\n");
if (buffer[3] & 8)
printf("\texternal request\n");
if (buffer[3] & 16)
printf("\tmedia\n");
if (buffer[3] & 32)
printf("\tmulti-host\n");
if (buffer[3] & 64)
printf("\tdevice busy\n");
printf("we are testing for : ");
switch (buffer[2]) {
case 0: printf("no requested event classes are supported\n"); break;
case 1: printf("operational change request/notification\n"); break;
case 2: printf("power management\n"); break;
case 3: printf("external request\n"); break;
case 4: printf("media\n"); break;
case 5: printf("multi-host\n"); break;
case 6: printf("device busy\n"); break;
case 7: printf("reserved\n"); break;
default: printf("notification class is bogus\n"); break;
}
printf("media event : ");
switch (buffer[4]) {
case 0: printf("no media change\n"); break;
case 1: printf("eject request\n"); break;
case 2: printf("new media\n"); break;
case 3: printf("media removal\n"); break;
case 4: printf("media change\n"); break;
default: printf("reserved code\n"); break;
}
printf("tray status : ");
if (buffer[5] & 1)
printf("empty\n");
else if (buffer[5] & 2)
printf("loaded\n");
else
printf("\n");
}