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

📄 growisofs_mmc.cpp

📁 linux平台下的dvd刻录软件
💻 CPP
📖 第 1 页 / 共 4 页
字号:
#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	    // 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...	    if (!dvddash && minv>(2*ONEX))		speed_factor /= 2.4;	    // some units, e.g. NEC ND-2500, offer 2x as minimal speed...	    else if (minv>=(2*ONEX))		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;   }		fprintf (stderr,":-( Failed to change write speed: "				"%d->%d\n",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",				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;  unsigned char  header[16],p32;  int            err;  class autofree page2A;    switch (profile)    {	case 0x1A:	// DVD+RW	    p32 = 0;	    dvddash = 0;	    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;	    dvddash = 0;	    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	    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 (dvd_compat)	p32 &= 0x3F;	// Single-session	    if (test_write)		p32 |= 0x10;	// Test Write for debugging purposes	    dvddash=1;	    break;	default:	    p32 = 0;	    dvddash = 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 = 256;			// bogus value    else    	buf_size = (p[12]<<8|p[13]);    if (buf_size<256)			// bogus value	buf_size = 256;    // GET PERFORMANCE/SET STREAMING are listed as mandatory, so that    // this is actually the most likely path...    if (set_speed_B6h (cmd,dvddash,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 = ONEX;	    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 < ONEX)			// 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<ONEX)			// must be bogus		velocity=0;	    if (v < minv)		minv = v;	}	if (!dvddash && minv>2*ONEX)	    // 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) 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==0x52000)	// "INVALID COMMAND"		break;		// LD-F321 doesn't support SEND OPC?	    if (err==0x52700)	// "WRITE PROTECTED"		break;		// Plextor PX-712A?	    if (err==0x17301)	// "POWER CALIBRATION AREA ALMOST FULL"	    {	fprintf (stderr,":-! WARNING: Power Calibration Area "	    			    "is almost full\n");		break;	    }	    sperror ("PERFORM OPC",err),	    exit(FATAL_START(errno));	} 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;    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,3000);    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"),

⌨️ 快捷键说明

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