> >  I have tried recording with "blank=all".  BTW, this makes the
> >machine unusable for more than 15 minutes (the duration of the
> >blanking operation),
> 
> That is happening with ATAPI and if you made the mistake to connect
> a hard disk to the same cable as the CD.

Of course it's easier to blame humans than technology. I mean I
disagree with "the mistake to connect units to same IDE cable"
clause as it's not a mistake nor should it be treated as one.
Because IDE channel doesn't have to be monopolize for blanking
[or finalizing for that matter] purposes. Attached code can
blank media for as long as it takes without rendering computer
useless by exploiting so called "IMMED" form of BLANK(A1h).
Yes, I'm aware that scsi_blank() [as well as scsi_close_tr_session()]
can issue "IMMED" commands, but as far as I can see they are never
actually deployed. And I fail to understand why...

Cheers. A.
8<------8<------8<------8<------8<------8<------8<------8<------8<------
/*
 * CD-RW blanking utility for Linux by <[EMAIL PROTECTED]>.
 *
 * This is proof-of-concept code! Point to be proven is that it's
 * possible to blank the CD-RW media [mounted in MMC-3 compliant unit]
 * *without* monopolizing the IDE bus.
 *
 * Note that the utility does not check [and therefore doesn't warn]
 * if the media already contains data so use it with caution!
 *
 * Use-it-on-your-own-risk, GPL bless...
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/cdrom.h>
#include <asm/param.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>

void usage (char *prog)
{ fprintf (stderr,"- usage: %s [-full] /dev/cdrom\n",prog),
  exit(1);
}

volatile int *progress;

void alarm_handler (int no)
{ static int    i=0,len=1,old_progress=0;
  static char   *str = "|/-\\",*backspaces="\b\b\b\b\b\b\b\b\b\b";
  int new_progress = *progress;
    if (new_progress != old_progress)
        len = fprintf (stderr,"%.*s%.1f%%",len,backspaces,
                                100.0*new_progress/65536.0) - len,
        old_progress = new_progress;
    else
        fprintf (stderr,"\b%c",str[i]),
        i++, i&=3;
    alarm(1);
}

void wait_for_unit (int fd)
{ struct cdrom_generic_command  cgc;
  struct request_sense sense;

    while (1)
    {   sleep(1);
        memset (&cgc,0,sizeof(cgc));
        cgc.cmd[0] = 0;         /* TEST UNIT READY      */
        cgc.quiet = 1;
        cgc.data_direction = CGC_DATA_NONE;
        memset (&sense,0,sizeof(sense));
        cgc.sense = &sense;
        if (ioctl (fd,CDROM_SEND_PACKET,&cgc) == 0) break;
        /*
         * I wish I could test for sense.valid, but (at least) hp dvd100i
         * returns 0 in valid bit at this point:-(
         */
        if (sense.error_code == 0)
            perror ("- [unable to TEST UNIT READY]"), exit(1);
        /*
         * MMC-3 (draft) specification says that the unit should return
         * progress indicator in key specific bytes even in reply to TEST
         * UNIT READY. Bit (at least) hp dvd100i doesn't and I have to
         * fetch it separately:-(
         */
        memset (&cgc,0,sizeof(cgc));
        cgc.buffer = (void *)&sense;
        cgc.buflen = sizeof (sense);
        cgc.data_direction = CGC_DATA_READ;
        cgc.cmd[0] = 0x03;      /* REQUEST SENSE        */
        cgc.cmd[4] = sizeof (sense);
        if (ioctl (fd,CDROM_SEND_PACKET,&cgc))
            perror ("- [unable to REQUEST SENSE]"), exit(1);
        if (sense.sks[0]&0x80)
            *progress = sense.sks[1]<<8|sense.sks[2];
    }
}

int main (int argc, char *argv[])
{ int                           fd;
  struct cdrom_generic_command  cgc;
  struct request_sense          sense;
  struct stat                   sb;
  unsigned char                 profile[8],*dev=NULL;
  int                           blankcode=1,len,i;
  pid_t                         pid;

    fprintf (stderr,"* CD-RW blanking utility by <[EMAIL PROTECTED]>\n");

    for (i=1;i<argc;i++) {
        if (*argv[i] == '-')
            if (argv[i][1] == 'f') blankcode = 0;
            else usage(argv[0]);
        else if (*argv[i] == '/')
            dev = argv[i];
        else
            usage (argv[0]);
    }

    if (dev==NULL) usage (argv[0]);

    if ((fd = open(dev,O_RDONLY|O_NONBLOCK)) < 0)
        fprintf (stderr,"- [unable to open(\"%s\")]: ",dev), perror (NULL),
        exit(1);

    if (fstat(fd,&sb) < 0)
        fprintf (stderr,"- [unable to stat(\"%s\")]: ",dev), perror (NULL),
        exit(1);

    if (!S_ISBLK(sb.st_mode))
        fprintf (stderr,"- [%s is not a block device]\n",dev),
        exit(1);

    memset (&cgc,0,sizeof(cgc));
    cgc.buffer = profile;
    cgc.buflen = 8;
    cgc.data_direction = CGC_DATA_READ;
    cgc.cmd[0] = 0x46;  /* GET CONFIGURATION    */
    cgc.cmd[8] = 8;
    if (ioctl (fd,CDROM_SEND_PACKET,&cgc))
        perror ("- [unable to GET CONFIGURATION]"),
        exit (1);

    if ((profile[6]<<8|profile[7]) != 0xA)
        fprintf (stderr, "- [mounted media doesn't appear to be CD-RW]\n"),
        exit (1);

    progress = 
mmap(NULL,sizeof(*progress),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
    if (progress == NULL)
        perror ("- [unable to mmap anonymously]"),
        exit(1);
    *progress = 0;

    if ((pid=fork()) == (pid_t)-1)
        perror ("- [unable to fork()]"),
        exit(1);

    if (pid)
    {   close (fd);
        fprintf (stderr,"* blanking .");
        signal (SIGALRM,alarm_handler);
        alarm(1);
        while ((waitpid(pid,&i,0) != pid) && !WIFEXITED(i)) ;
        if (WEXITSTATUS(i) == 0) fprintf (stderr,"\n");
        return 0;
    }

    /*
     * You can suspend, terminate, etc. the parent. We will keep on
     * working in background...
     */
    setsid();

    memset (&cgc,0,sizeof(cgc));
    cgc.data_direction = CGC_DATA_NONE;
    cgc.sense = &sense;
    cgc.cmd[0] = 0xA1;  /* BLANK                        */
    cgc.cmd[1] = 0x10 | blankcode; /* "IMMED" code      */
    if (ioctl (fd,CDROM_SEND_PACKET,&cgc))
        fprintf (stderr,"- [unable to BLANK (%xh/%xh/%xh)]: ",
                        sense.sense_key,sense.asc,sense.ascq), perror (NULL),
        exit(1);

    wait_for_unit (fd);

    if (ioctl (fd,CDROM_MEDIA_CHANGED,0) == 0)
    {   if (ioctl (fd,CDROMEJECT))
            perror ("- [failed to OPEN TRAY]"), exit (1);
        if (ioctl (fd,CDROMCLOSETRAY))
            perror ("- [failed to CLOSE TRAY]"), exit (1);
    }

  return 0;
}


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to