> > 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]