📄 dvd+rw-mediainfo.cpp
字号:
/* * DVD Media Info utility by Andy Polyakov <appro@fy.chalmers.se>. * * This code is in public domain. */#include <stdio.h>#include <stddef.h>#include <stdlib.h>#include <string.h>#include "transport.hxx"int main(int argc,char *argv[]){ Scsi_Command cmd; unsigned char header[40],inq[128],*page2A=NULL; char cmdname[64]; int i,j,ntracks,err,dvd_dash=0,dvd_plus=0, plus_mediaid_printed=0,page2A_printed=0,dvd_ram_spare=0; unsigned short profile,dvd_0E=0,dvd_10=0,dvd_11=0,dvd_0A=0,dvd_C0=0; if (argc<2) fprintf (stderr,"usage: %s /dev/dvd\n",argv[0]), exit (1); if (!cmd.associate(argv[1])) fprintf (stderr,"%s: unable to open: ",argv[1]), perror (NULL), exit (1); cmd[0] = 0x12; // INQUIRY cmd[4] = 36; cmd[5] = 0; if ((err=cmd.transport(READ,inq,36))) sperror ("INQUIRY",err), exit (1); if ((inq[0]&0x1F) != 5) fprintf (stderr,":-( not an MMC unit!\n"), exit (1); if (argc>1) printf ("INQUIRY: [%.8s][%.16s][%.4s]\n", inq+8,inq+16,inq+32);#if 0 wait_for_unit(cmd);#else // consume sense data, most commonly "MEDIUM MAY HAVE CHANGED"... cmd[0] = 0; // TEST UNIT READY cmd[5] = 0; if ((err=cmd.transport()) == -1) sperror ("TEST UNIT READY",err), exit (1);#endif if (argc>2) do { unsigned char *pages; int len,n; static int pagecode=0x3F; printf ("MODE SENSE[#%02Xh]:\n",pagecode); cmd[0] = 0x5A; // MODE SENSE cmd[1] = 0x08; // "Disable Block Descriptors" cmd[2] = pagecode; // initially "All Pages" cmd[8] = 12; cmd[9] = 0; if ((err=cmd.transport(READ,header,12))) sprintf (cmdname,"MODE SENSE#%02X",pagecode), sperror (cmdname,err), exit(1); if (header[6]<<8|header[7]) fprintf (stderr,":-( \"DBD\" is not respected\n"), exit(1); len=(header[0]<<8|header[1])+2; if (len < (8+2+header[9])) { if (pagecode == 0x3F) { pagecode = 0x5; continue; } len = 8+2+header[9]; } if (!(pages=(unsigned char *)malloc(len))) exit(1); cmd[0] = 0x5A; cmd[1] = 0x08; cmd[2] = pagecode; cmd[7] = len>>8; cmd[8] = len; cmd[9] = 0; cmd.transport(READ,pages,len); for(i=8+(pages[6]<<8|pages[7]);i<len;) { if (pages[i] == 0) break; if (pages[i] == 0x2A) page2A_printed=1; printf (" %02X:",pages[i++]); n=pages[i++]; for (j=0;j<n;j++) { if (j && j%16==0) printf("\n"); printf ("%c%02x",(j%16)?' ':'\t',pages[i++]); } printf("\n"); } if (i<len) { printf (" RES:"); for (len-=i,j=0;j<len;j++) { if (j && j%16==0) printf("\n"); printf ("%c%02x",(j%16)?' ':'\t',pages[i++]); } printf ("\n"); } free(pages); break; } while (1); { int len,n; page2A=header, len=36; while (1) { cmd[0] = 0x5A; // MODE SENSE(10) cmd[1] = 0x08; // "Disable Block Descriptors" cmd[2] = 0x2A; // "Capabilities and Mechanical Status" cmd[7] = len>>8; cmd[8] = len; cmd[9] = 0; if ((err=cmd.transport(READ,page2A,len))) sperror ("MODE SENSE#2A",err), exit (1); if (page2A[6]<<8|page2A[7]) fprintf (stderr,":-( \"DBD\" is not respected\n"); else if (len<((page2A[0]<<8|page2A[1])+2) || len<(8+2+page2A[9])) { len=(page2A[0]<<8|page2A[1])+2; if (len < (8+2+page2A[9])) len = 8+2+page2A[9]; page2A=(unsigned char *)malloc(len); continue; } if (!(page2A[8+(page2A[6]<<8|page2A[7])+2]&8)) fprintf (stderr,":-( not a DVD unit\n"), exit (1); if (page2A==header) page2A=NULL; else if (argc>2 && !page2A_printed) { printf("MODE SENSE[#2A]:\n"); for(i=8+(page2A[6]<<8|page2A[7]);i<len;) { printf (" %02X:",page2A[i++]); n=page2A[i++]; for (j=0;j<n;j++) { if (j && j%16==0) printf("\n"); printf ("%c%02x",(j%16)?' ':'\t',page2A[i++]); } printf("\n"); } } break; } } do { unsigned int len,j; unsigned char *p; cmd[0] = 0xAD; cmd[7] = 0xFF; cmd[9] = 4; cmd[11] = 0; if ((err=cmd.transport(READ,header,4))) { if (argc>2) sperror ("READ DVD STRUCTURE#FF",err); break; } len = (header[0]<<8|header[1]) + 2; if (!(p = (unsigned char *)malloc(len))) break; cmd[0] = 0xAD; cmd[7] = 0xFF; cmd[8] = len>>8; cmd[9] = len; cmd[11] = 0; if ((err=cmd.transport(READ,p,len))) break; for (j=4;j<len;j+=4) switch (p[j]) { case 0x0A: dvd_0A=p[j+2]<<8|p[j+3]; break; case 0x0E: dvd_0E=p[j+2]<<8|p[j+3]; break; case 0x10: dvd_10=p[j+2]<<8|p[j+3]; break; case 0x11: dvd_11=p[j+2]<<8|p[j+3]; break; case 0xC0: dvd_C0=p[j+2]<<8|p[j+3]; break; } if (argc<=2) break; printf ("READ DVD STRUCTURE[#FF]:\n"); for (j=4;j<len;j+=4) printf(" STRUCTURE#%02x %02x:%d\n",p[j],p[j+1],p[j+2]<<8|p[j+3]); } while (0); cmd[0] = 0x46; // GET CONFIGURATION cmd[1] = 1; cmd[8] = 8; cmd[9] = 0; if ((err=cmd.transport(READ,header,8))) { if (err!=0x52000) // "IVALID COMMAND OPERATION CODE" sperror ("GET CONFIGURATION",err), perror (NULL), exit(1); profile=0x10; // non MMC3 DVD-ROM unit? goto legacy; } profile=header[6]<<8|header[7]; printf ("GET [CURRENT] CONFIGURATION:\n"); if (argc>2) { unsigned char *profiles; int len,n; len=header[2]<<8|header[3]; len+=4; if (!(profiles=(unsigned char *)malloc(len))) exit(1); cmd[0] = 0x46; cmd[1] = 1; cmd[6] = len>>16; cmd[7] = len>>8; cmd[8] = len; cmd[9] = 0; cmd.transport(READ,profiles,len); for(i=8;i<len;) { printf (" %04X%c",profiles[i]<<8|profiles[i+1],':'); n=profiles[i+3]; i+=4; for (j=0;j<n;j++) { if (j && j%16==0) printf("\n"); printf ("%c%02x",(j%16)?' ':'\t',profiles[i++]); } printf("\n"); } free(profiles); } if (profile==0) fprintf (stderr,":-( no media mounted, exiting...\n"), exit(1); if ((profile&0xF0) != 0x10 && profile != 0x2B) fprintf (stderr,":-( non-DVD media mounted, exiting...\n"), exit (1); { const char *str; switch (profile) { case 0x10: str="-ROM"; break; case 0x11: str="-R Sequential"; break; case 0x12: str="-RAM"; break; case 0x13: str="-RW Restricted Overwrite"; break; case 0x14: str="-RW Sequential"; break; case 0x1A: str="+RW"; break; case 0x1B: str="+R"; break; case 0x2B: str="+R Double Layer"; break; default: str="unknown"; break; } printf (" Mounted Media: %Xh, DVD%s\n",profile,str); if (str[0]=='-' && str[3]!='M') dvd_dash=0x10; if (str[0]=='+') dvd_plus=0x11; } if (dvd_0E || dvd_11) do { union { unsigned char _e[4+40],_11[4+256]; } dvd; unsigned int len; unsigned char format=dvd_dash?0x0E:0x11; cmd[0] = 0xAD; cmd[7] = format; cmd[9] = 4; cmd[11] = 0; if ((err=cmd.transport(READ,header,4))) { if (argc>2) sprintf (cmdname,"READ DVD STRUCTURE#%02x",format), sperror (cmdname,err); break; } len = (header[0]<<8|header[1]) + 2; if (len>sizeof(dvd)) len=sizeof(dvd); cmd[0] = 0xAD; cmd[7] = format; cmd[8] = len>>8; cmd[9] = len; cmd[11] = 0; if ((err=cmd.transport(READ,&dvd,len))) break; if (argc>2) { printf ("READ DVD STRUCTURE[#%02xh]:",format); for (j=0,i=dvd_dash?sizeof(dvd._e):sizeof(dvd._11);j<i;j++) printf("%c%02x",j?' ':'\t',dvd._11[j]); printf("\n"); } if (dvd_dash && dvd_0E && dvd._e[4+16]==3 && dvd._e[4+24]==4) printf (" Media ID: %6.6s%-6.6s\n",dvd._e+4+17,dvd._e+4+25); if (dvd_plus && dvd_11) printf (" Media ID: %.8s/%.3s\n",dvd._11+23,dvd._11+31), plus_mediaid_printed=1; } while (0); if (page2A) do { int len,hlen,v,n=0; unsigned char *p; len = (page2A[0]<<8|page2A[1])+2; hlen = 8+(page2A[6]<<8|page2A[7]); if (len<(hlen+30)) break; // no "Current Write Speed" p = page2A+hlen; v = p[28]<<8|p[29]; // Check Write Speed descriptors for sanity. Some DVD+units // return CD-R descriptors here, which has no meaning in the // context of interest. if (v<1352) break; if (len>=(hlen+32)) { n = (p[30]<<8|p[31])*4; for (i=0;i<n;i+=4) if ((p[32+i+2]<<8|p[32+i+3]) < 1352) break; if (i<n) break; } printf (" Current Write Speed: %.1fx1385=%dKB/s\n",v/1385.0,v); if (len<(hlen+32)) break; // no "Write Speed Descriptors" for (i=0;i<n;i+=4) v = p[32+i+2]<<8|p[32+i+3], printf (" Write Speed #%d: %.1fx1385=%dKB/s\n",i/4,v/1385.0,v); } while (0); do { unsigned char d[8+16],*p; unsigned int len,rv,wv,i; cmd[0]=0xAC; // GET PERFORMANCE cmd[1]=4; // ask for "Overall Write Performance" cmd[9]=1; // start with one descriptor cmd[10]=0; // ask for descriptor in effect cmd[11]=0; if ((err=cmd.transport(READ,d,sizeof(d)))) { if (argc>2) sperror ("GET CURRENT PERFORMACE",err); break; } len = (d[0]<<24|d[1]<<16|d[2]<<8|d[3])-4; if (len%16) // insane length { if (argc>2) fprintf (stderr,":-( insane GET PERFORMANCE length %u\n",len); break; } len+=8; if (len < sizeof(d)) { if (argc>2) fprintf (stderr,":-( empty GET CURRENT PERFORMACE descriptor\n"); break; } if (len == sizeof(d)) p = d; else // ever happens? { unsigned int n=(len-8)/16; p = (unsigned char *)malloc(len); // will leak... cmd[0]=0xAC; // GET PERFORMANCE cmd[1]=4; // ask for "Overall Write Performance" cmd[8]=n>>8; cmd[9]=n; // real number of descriptors cmd[10]=0; // ask for descriptor in effect cmd[11]=0; if ((err=cmd.transport(READ,p,len))) { sperror ("GET CURRENT PERFORMANCE",err); break; } } if (argc>2) { printf ("GET CURRENT PERFORMANCE:\t"); for (i=4;i<len;i++) printf ("%02x ",p[i]); printf ("\n"); } if ((p[4]&2) == 0) fprintf (stderr,":-( reported write performance might be bogus\n"); if (argc<=2) printf ("GET [CURRENT] PERFORMANCE:\n"); for (p+=8,len-=8,i=0;len;p+=16,len-=16,i++) { rv=p[4]<<24 |p[5]<<16 |p[6]<<8 |p[7], wv=p[12]<<24|p[13]<<16|p[14]<<8|p[15]; if (rv==wv) printf (" %-23s%.1fx1385=%uKB/s@[%u -> %u]\n", i==0?"Write Performance:":"", rv/1385.0,rv, p[0]<<24|p[1]<<16|p[2]<<8 |p[3], p[8]<<24|p[9]<<16|p[10]<<8|p[11]); else printf (" %-23s%.1fx1385=%uKB/s@%u -> %.1fx1385=%uKB/s@%u\n", i==0?"Write Performance:":"", rv/1385.0,rv,p[0]<<24|p[1]<<16|p[2]<<8 |p[3], wv/1385.0,wv,p[8]<<24|p[9]<<16|p[10]<<8|p[11]); } } while (0); do { unsigned char d[8+16],*p; unsigned int len,rv,wv,i; cmd[0]=0xAC; // GET PERFORMANCE cmd[9]=1; // start with one descriptor cmd[10]=0x3; // ask for "Write Speed Descriptor" cmd[11]=0; if ((err=cmd.transport(READ,d,sizeof(d)))) { if (argc>2) sperror ("GET PERFORMACE",err); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -