⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 growisofs_mmc.cpp

📁 最新的linux下dvd刻录软件,支持DVD+RW、DVD-RW光盘刻录。
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    perf = (unsigned char *)malloc(len+=8);    if (perf == NULL)	fprintf (stderr,":-( memory exhausted\n"),	exit(FATAL_START(ENOMEM));    if (len == sizeof(d))	memcpy (perf,d,sizeof(d));    else    { unsigned int n=(len-8)/16;	cmd[0]=0xAC;		// GET PERFORMANCE	cmd[8]=n>>8;	cmd[9]=n;		// real number of descriptors	cmd[10]=0x3;		// ask for "Write Speed Descriptor"	cmd[11]=0;	if ((err=cmd.transport(READ,perf,len)))	    sperror ("GET PERFORMANCE",err),	    exit (FATAL_START(errno));    }    int targetv=0,errp=0;    do {	memset (d,0,sizeof(d));	cmd[0]=0xAC;		// GET PERFORMANCE	cmd[1]=4;		// ask for "Overall Write performance"	cmd[9]=1;	cmd[10]=0;		// ask for descriptor in effect	cmd[11]=0;	if (errp || (errp=cmd.transport(READ,d,sizeof(d))))#if 0	    sperror ("GET CURRENT PERFORMANCE",errp),	    exit (FATAL_START(errno));	// well, if it passed above, we					// expect it to pass this too...#else	// Pioneer doesn't report current speed through GET PERFORMANCE:-(	{   emulated_err:	    if (page2A == NULL)	return -1;	    unsigned int  plen,hlen;	    plen = (page2A[0]<<8|page2A[1]) + 2;	    hlen = 8 + (page2A[6]<<8|page2A[7]);	    unsigned char * const p = page2A + hlen;	    if (plen<(hlen+32) || p[1]<(32-2))		return -1;	// well, SET CD SPEED wouldn't work...	    velocity = p[28]<<8|p[29];	}#endif	else if ((errp = pull_velocity (cmd,d)) < 0)		goto emulated_err;	if (speed_factor != 0.0)	{ int i,j=len-8,v,v0,v1,minv,closesti,closestv=0;	  unsigned char *wsdp=perf+8;	    for (minv=0x7fffffff,i=0;i<j;i+=16)	    {	v=wsdp[i+12]<<24|wsdp[i+13]<<16|wsdp[i+14]<<8|wsdp[i+15];		if (v<minv) minv=v;	    } // minv will be treated as 1x	    // New generation units offer minimum velocities other than 1x	    if      (minv>(15*_1x))	speed_factor /= 16.0;	    else if (minv>(11*_1x))	speed_factor /= 12.0;	    else if (minv>(7*_1x))	speed_factor /= 8.0;	    else if (minv>(5*_1x))	speed_factor /= 6.0;	    else if (minv>(3*_1x))	speed_factor /= 4.0;		    else if (dvdplus && minv>(2*DVD_1X))		// 2.4x is like 1x for DVD+, but it turned out that there're		// units, most notably "DVDRW IDE1004," burning DVD+ at		// lower speed, so I have to watch out for it...		speed_factor /= 2.4;	    else if (minv>=(2*_1x))		speed_factor /= 2.0;	    v0=(int)(speed_factor*minv + 0.5);	    for (closesti=0,minv=0x7fffffff,i=0;i<j;i+=16)	    {	v1=wsdp[i+12]<<24|wsdp[i+13]<<16|wsdp[i+14]<<8|wsdp[i+15];		v=abs(v0-v1);		if (v<minv) minv=v, closesti=i, closestv=v1;	    } // currenti is index of descriptor with *closest* velocity	    targetv=closestv;	    speed_factor=0.0;	    if (velocity==targetv)		break;	// already in shape, nothing to do...	    unsigned char pd[28];	    memset (pd,0,sizeof(pd));	// setup "Performance Descriptor"	    pd[0]=*(wsdp+closesti);	// copy "WRC" and other flags#if 0	    memset(pd+8,0xFF,4);#else	    // I might have to copy the value from current descriptor...	    unsigned int cap=get_2k_capacity(cmd)-1;	    pd[8]=cap>>24;	    pd[9]=cap>>16;	    pd[10]=cap>>8;	    pd[11]=cap;#endif	    memcpy(pd+12,wsdp+closesti+8,4);	// copy "Read Speed"	    memcpy(pd+20,wsdp+closesti+12,4);	// copy "Write Speed"	    pd[18]=pd[26]=1000>>8;		// set both "Read Time" and	    pd[19]=pd[27]=1000&0xFF;		// "Write Time" to 1000ms	    cmd[0]=0xB6;		// SET STREAMING	    cmd[10]=sizeof(pd);	    cmd[11]=0;	    if ((err=cmd.transport (WRITE,pd,sizeof(pd))))		sperror ("SET STREAMING",err),		exit (FATAL_START(errno));	    // I pull the Page 2A in either case, because unit might	    // have provided irrelevant information (Plextor). Not to	    // mention cases when it simply failed to reply to GET	    // CURRENT PERFORMANCE (Pioneer, LG).	    unsigned int plen  = (page2A[0]<<8|page2A[1]) + 2;	    cmd[0] = 0x5A;	// MODE SENSE	    cmd[1] = 0x08;	// "Disable Block Descriptors"	    cmd[2] = 0x2A;	// "Capabilities and Mechanical Status"	    cmd[7] = plen>>8;	    cmd[8] = plen;	// real length this time	    cmd[9] = 0;	    if ((err=cmd.transport(READ,page2A,plen)))		sperror ("MODE SENSE#2A",err),		exit(FATAL_START(errno));	}	else if (targetv)	{   if (targetv!=velocity)	    {	if (errp==0)	// check Page 2A for speed then...		{   errp=-1; continue;   }		if (velocity==0 || velocity>=_1x)		{   fprintf(stderr,":-? Failed to change write speed: %d->%d\n",					(int)velocity,targetv);		    if (velocity<targetv)	velocity=targetv;		}		else		{   fprintf(stderr,":-( Failed to change write speed: %d->%d\n",					(int)velocity,targetv);		    exit (FATAL_START(EINVAL));		}	    }	    break;	}    } while (targetv);  return targetv;}static int set_speed_BBh (Scsi_Command &cmd,unsigned char *page2A){ unsigned int   plen,hlen;  int err;    plen  = (page2A[0]<<8|page2A[1]) + 2;    hlen = 8 + (page2A[6]<<8|page2A[7]);    unsigned char * const p = page2A + hlen;    if (plen<(hlen+32) || p[1]<(32-2))	return -1;    int targetv=0;    do {	velocity = p[28]<<8|p[29];	if (speed_factor != 0.0)	{ int i,j,v,v0,v1,minv,closesti,closestv=0;	  unsigned char *wsdp=p+32;	    j=(p[30]<<8|p[31])*4;	    for (minv=0x7fffffff,i=0;i<j;i+=4)	    {	v=wsdp[i+2]<<8|wsdp[i+3];		if (v<minv) minv=v;	    } // minv will be treated as 1x	    v0=(int)(speed_factor*minv + 0.5);	    for (closesti=0,minv=0x7fffffff,i=0;i<j;i+=4)	    {	v1=wsdp[i+2]<<8|wsdp[i+3];		v=abs(v0-v1);		if (v<minv) minv=v, closesti=i, closestv=v1;	    } // currenti is index of descriptor with *closest* velocity	    targetv=closestv;	    speed_factor=0.0;	    if (velocity==targetv)		break;	// already in shape, nothing to do...	    cmd[0]=0xBB;		// SET CD SPEED	    cmd[1]=wsdp[closesti+1];	// Rotation Control	    cmd[2]=cmd[3]=0xff;		// Read Speed	    cmd[4]=wsdp[closesti+2];	// Write Speed	    cmd[5]=wsdp[closesti+3];	    cmd[11]=0;	    if ((err=cmd.transport()))		sperror ("SET CD SPEED",err),		exit (FATAL_START(errno));	    cmd[0] = 0x5A;	// MODE SENSE	    cmd[1] = 0x08;	// "Disable Block Descriptors"	    cmd[2] = 0x2A;	// "Capabilities and Mechanical Status"	    cmd[7] = plen>>8;	    cmd[8] = plen;	// real length this time	    cmd[9] = 0;	    if ((err=cmd.transport(READ,page2A,plen)))		sperror ("MODE SENSE#2A",err),		exit(FATAL_START(errno));	}	else if (targetv)	{   if (targetv!=velocity)		fprintf (stderr,":-( Failed to change write speed: %d->%d\n",				(int)velocity,targetv),		exit (FATAL_START(EINVAL));	    break;	}    } while (targetv);  return targetv;}static int plusminus_pages_setup (Scsi_Command &cmd,int profile){ unsigned int   plen,hlen,dvddash=0,dvdplus=0;  unsigned char  header[16],p32;  int            err;  class autofree page2A;    switch (profile)    {	case 0x1A:	// DVD+RW	    p32 = 0;	    dvdplus=1;	    break;	case 0x1B:	// DVD+R	    //	    // Even though MMC-4 draft explicitely exempts DVD+RW/+R media	    // from those being affected by Page 05h settings, some	    // firmwares apparently pay attention to Multi-session flag	    // when finalizing DVD+R media. Well, we probably can't blame	    // vendors as specification is still a work in progress, not to	    // mention that it was published after DVD+R was introduced to	    // the market.	    //	    p32 = dvd_compat?0x02:0xC0;	    dvdplus=1;	    break;	case 0x13:	// DVD-RW Restricted Overwrite	    p32 = 0xC0;	// NB! Test Write in not option here	    dvddash = 1;	    break;	case 0x11:	// DVD-R Sequential	case 0x14:	// DVD-RW Sequential	case 0x15:	// DVD-R Dual Layer Sequential	    p32 = 0xC0;	    if (next_track==1) do	    {	if (dvd_compat >= (profile==0x14?2:256))		{   is_dao = 1,		    fprintf (stderr,"%s: engaging DVD-%s DAO upon user request...\n",				    ioctl_device,profile==0x14?"RW":"R");		    break;		}		// Try to figure out if we have to go for DAO...		cmd[0] = 0x46;	// GET CONFIGURATION		cmd[1] = 2;	// ask for the only feature...		cmd[3] = 0x21;	// the "Incremental Streaming Writable" one		cmd[8] = 16;	// The feature should be there, right?		cmd[9] = 0;		if ((err=cmd.transport (READ,header,16)))		    sperror ("GET FEATURE 21h",err),		    exit(FATAL_START(errno));		hlen = header[0]<<24|header[1]<<16|header[2]<<8|header[3];		// See if Feature 21h is "current," if not, engage DAO...		if (hlen>=12 && (header[8+2]&1)==0)		{   is_dao = dvd_compat = 1;		    fprintf (stderr,"%s: FEATURE 21h is not on, engaging DAO...\n",				    ioctl_device);		    break;		}	    } while (0);		    if (is_dao)		p32 |=2;	// DAO	    if (profile==0x15 || // DVD-R DL Seq has no notion of multi-session		dvd_compat)	p32 &= 0x3F;	// Single-session	    if (test_write)		p32 |= 0x10;	// Test Write for debugging purposes	    dvddash=1;	    break;	case 0x16:	// DVD-R Dual Layer Jump	    p32 = 0xC0;	    p32 |= 4;	// Jump	    if (test_write)		p32 |= 0x10;	// Test Write for debugging purposes	    dvddash=1;	    break;	default:	    p32 = 0;	    break;    }    if (dvddash || p32)	page05_setup (cmd,profile,p32);    page2A = pull_page2A (cmd);    plen = (page2A[0]<<8|page2A[1]) + 2;    hlen = 8 + (page2A[6]<<8|page2A[7]);    unsigned char * const p = page2A + hlen;    if (plen<(hlen+14) || p[1]<(14-2))	// no "Buffer Size Supported"	buf_size = 512;			// bogus value    else    	buf_size = (p[12]<<8|p[13]);    if (buf_size<512)			// bogus value	buf_size = 512;    // GET PERFORMANCE/SET STREAMING are listed as mandatory, so that    // this is actually the most likely path...    if (set_speed_B6h (cmd,dvdplus,page2A) >= 0)	goto opc;    if (plen<(hlen+30) || p[1]<(30-2))	// no "Current Write Speed" present    {	if (dvddash)	{   fprintf (stderr,":-( \"Current Write Speed\" descriptor "			    "is not present, faking 1x...\n"),	    velocity = _1x;	    speed_factor = 0.0;	}	else	    velocity = 0;    }    else do    {	velocity = p[28]<<8|p[29];	// Some units, most notably NEC and derivatives, were observed	// to report CD-R descriptors...	if (velocity < DVD_1X)			// must be bogus	{   velocity=0;	    break;	}	if (plen<(hlen+32) || p[1]<(32-2))	// no write descriptors	    break;	int            n = p[30]<<8|p[31],minv=1<<16;	unsigned char *p_= p+32;	for (;n--;p_+=4)	{   int v=p_[2]<<8|p_[3];	    if (v==0) continue;		// Lite-On returns zeros here...	    if (v<_1x)			// must be bogus		velocity=0;	    if (v < minv)		minv = v;	}	if (dvdplus && minv>2*_1x)	    // See corresponding comment in set_speed_B6h()	    speed_factor /= 2.4;    } while (0);    if (speed_factor != 0.0 &&	(velocity==0 || set_speed_BBh (cmd,page2A)<0) )	fprintf (stderr,":-( can't control writing velocity, "			"-speed option is ignored\n");opc:    if (!dvddash || test_write || no_opc) return 0;    // See if OPC is required...    cmd[0] = 0x51;	// READ DISC INFORMATION    cmd[8] = 8;    cmd[9] = 0;    if ((err=cmd.transport (READ,header,8)))	sperror ("READ DISC INFORMATION",err),	exit(FATAL_START(errno));    if ((header[0]<<8|header[1]) <= 0x20)    {	cmd[0] = 0x54;	// SEND OPC INFORMATION	cmd[1] = 1;	// "Perform OPC"	cmd[9] = 0;	cmd.timeout(120);	// NEC units can be slooo...w	if ((err=cmd.transport())) do	{   if (err==0x17301)	// "POWER CALIBRATION AREA ALMOST FULL"	    {	fprintf (stderr,":-! WARNING: Power Calibration Area "	    			    "is almost full\n");		break;	    }	    sperror ("PERFORM OPC",err);	    if ((err&0x0FF00)==0x07300)	exit(FATAL_START(errno));	    /*	     * Th rest of errors are ignored, most notably observed:	     * 0x52000, "INVALID COMMAND"		Panasonic LD-F321	     * 0x52700, "WRITE PROTECTED"		Plextor PX-712A	     * 0x52C00, "COMMAND SEQUENCE ERROR"	Plextor PX-716UF	     * 0x53002, "MEDIA NOT SUPPORTED"		Toshiba TS-H542A	     */	} while (0);    }    handle_events(cmd);  return 0;}static int minus_rw_quickgrow (Scsi_Command &cmd,off64_t size){ unsigned char	format[12];  unsigned int	lead_out,blocks,type;  int		i,len,err;    type = formats[4+4]&3;    if (type==2 && size!=0)    {	blocks = size/2048;	blocks += 15, blocks &= ~15;	lead_out = 0;	lead_out |= formats[4+0], lead_out <<= 8;	lead_out |= formats[4+1], lead_out <<= 8;	lead_out |= formats[4+2], lead_out <<= 8;	lead_out |= formats[4+3];	if (blocks<=lead_out)	// no need to grow the session...	    return 0;    }    // look for Quick Grow descriptor...    for (i=8,len=formats[3];i<len;i+=8)	if ((formats [4+i+4]>>2) == 0x13) break;    if (i==len)			// no Quick Grow descriptor    {	if (type != 2)	    quickgrown=1;	// in reality quick formatted...	return 0;    }    else    {	blocks = 0;	blocks |= formats[i+0], blocks <<= 8;	blocks |= formats[i+1], blocks <<= 8;	blocks |= formats[i+2], blocks <<= 8;	blocks |= formats[i+3];	if (type==2 && blocks==0)	// nowhere no grow...	    return 0;    }    quickgrown=1;    fprintf (stderr,"%s: \"Quick Grow\" session...\n",ioctl_device);    memset (format,0,sizeof(format));    format [1] = 2;		// "IMMED"    format [3] = 8;		// "Length"    format [8] = 0x13<<2;	// "Quick Grow"    format [11] = 16;    cmd[0] = 0x4;		// FORMAT UNIT    cmd[1] = 0x11;    cmd[5] = 0;    if ((err=cmd.transport (WRITE,format,sizeof(format))))    {	sperror ("QUICK GROW",err);	return 1;    }  return wait_for_unit (cmd);}static int minus_r_reserve_track (Scsi_Command &cmd,off64_t size){ int          err;  unsigned int blocks;    blocks = size/2048;    if (is_dao)	dao_blocks = blocks;    else	blocks += 15, blocks &= ~15;    fprintf (stderr,"%s: reserving %u blocks",ioctl_device,blocks);    if (is_dao && blocks<380000)	fprintf (stderr,"\b, warning for short DAO recording"),	poll (NULL,0,5000);    fprintf (stderr,"\n");			    cmd[0] = 0x53;		// RESERVE TRACK    cmd[5] = blocks>>24;    cmd[6] = blocks>>16;    cmd[7] = blocks>>8;    cmd[8] = blocks;    cmd[9] = 0;    if ((err=cmd.transport ()))    {	sperror ("RESERVE TRACK",err);	return 1;    }  return 0;}static void plus_r_dl_split (Scsi_Command &cmd,off64_t size){ int           err;  unsigned int  blocks,split;  unsigned char dvd_20[4+8];    cmd[0] = 0xAD;	// READ DVD STRUCTURE    cmd[7] = 0x20;	// "DVD+R Double Layer Boundary Information"    cmd[9] = sizeof(dvd_20);    cmd[11] = 0;    if ((err=cmd.transport(READ,dvd_20,sizeof(dvd_20))))    	sperror ("READ DVD+R DL BOUNDARY INFORMATION",err),	exit (FATAL_START(errno));    if ((dvd_20[0]<<8|dvd_20[1]) < 10) 	fprintf (stderr,":-( insane DVD+R DL BI structure length\n"),	exit (FATAL_START(EINVAL));    if (dvd_20[4]&0x80)    {	fprintf (stderr,":-? L0 Data Zone Capacity is set already\n");	return;    }    split = dvd_20[8]<<24|dvd_20[9]<<16|dvd_20[10]<<8|dvd_20[11];    blocks = size/2048;    blocks += 15, blocks &= ~15;    if (blocks <= split)	fprintf (stderr,":-( more than 50%% of space will be *wasted*!\n"			"    use single layer media for this recording\n"),	exit (FATAL_START(EMEDIUMTYPE));    blocks /= 16;    blocks += 1;    blocks /= 2;    blocks *= 16;    fprintf (stderr,"%s: splitting layers at %u blocks\n",		    ioctl_device,blocks);    memset (dvd_20,0,sizeof(dvd_20));    dvd_20[1]  = sizeof(dvd_20)-2;    dvd_20[8]  = blocks>>24;    dvd_20[9]  = blocks>>16;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -