📄 cdtester.c
字号:
/* * cdtester.c -- test the audio functions of a CD driver * * (c) 1995 Eberhard Moenkeberg <emoenke@gwdg.de> * published under the GPL * * made under heavy use of the "Tiny Audio CD Player" * from Werner Zimmermann <zimmerma@rz.fht-esslingen.de> * (see linux/drivers/block/README.aztcd) * * Minor changes by Jeff Tranter to remove compile warnings * */#undef AZT_PRIVATE_IOCTLS /* not supported by every CDROM driver */#define SBP_PRIVATE_IOCTLS /* not supported by every CDROM driver */#include <sys/types.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <malloc.h>#include <ctype.h>#include <sys/ioctl.h>#include <linux/cdrom.h>#ifdef AZT_PRIVATE_IOCTLS#include <linux/aztcd.h>#endif AZT_PRIVATE_IOCTLS#ifdef SBP_PRIVATE_IOCTLS#include <linux/sbpcd.h>#include <linux/fs.h>#endif SBP_PRIVATE_IOCTLSstruct cdrom_tochdr hdr;struct cdrom_tochdr tocHdr;struct cdrom_tocentry TocEntry[101];struct cdrom_tocentry entry;struct cdrom_multisession ms_info;struct cdrom_read_audio read_audio;struct cdrom_ti ti;struct cdrom_subchnl subchnl;struct cdrom_msf msf;struct cdrom_volctrl volctrl;#ifdef AZT_PRIVATE_IOCTLSunion{ struct cdrom_msf msf; unsigned char buf[CD_FRAMESIZE_RAW];} azt;#endif AZT_PRIVATE_IOCTLSint i, i1, i2, i3, j, k;unsigned char sequence=0;unsigned char command[80];unsigned char first=1, last=1;char *default_device="/dev/cdrom";char dev[20];char filename[20];int drive;int datafile;int rc;void help(void){ printf("Available Commands:\n"); printf("STOP s EJECT e QUIT q\n"); printf("PLAY TRACK t PAUSE p RESUME r\n"); printf("NEXT TRACK n REPEAT LAST l HELP h\n"); printf("SUBCHANNEL_Q c TRACK INFO i PLAY AT a\n"); printf("READ d READ RAW w READ AUDIO A\n"); printf("MS-INFO M TOC T START S\n"); printf("SET EJECTSW X DEVICE D DEBUG Y\n"); printf("AUDIO_BUFSIZ Z RESET R BLKRASET B\n"); printf("SET VOLUME v GET VOLUME V\n");}/* * convert MSF number (3 bytes only) to Logical_Block_Address */int msf2lba(u_char *msf){ int i; i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_BLOCK_OFFSET; if (i<0) return (0); return (i);}/* * convert logical_block_address to m-s-f_number (3 bytes only) */void lba2msf(int lba, unsigned char *msf){ lba += CD_BLOCK_OFFSET; msf[0] = lba / (CD_SECS*CD_FRAMES); lba %= CD_SECS*CD_FRAMES; msf[1] = lba / CD_FRAMES; msf[2] = lba % CD_FRAMES;}int init_drive(char *dev){ unsigned char msf_ent[3]; /* * open the device */ drive=open(dev,0); if (drive<0) return (-1); /* * get TocHeader */ printf("getting TocHeader...\n"); rc=ioctl(drive,CDROMREADTOCHDR,&hdr); if (rc!=0) { printf("can't get TocHeader (error %d).\n",rc); return (-2); } else first=hdr.cdth_trk0; last=hdr.cdth_trk1; printf("TocHeader: %d %d\n",hdr.cdth_trk0,hdr.cdth_trk1); /* * get and display all TocEntries */ printf("getting TocEntries...\n"); for (i=1;i<=hdr.cdth_trk1+1;i++) { if (i!=hdr.cdth_trk1+1) TocEntry[i].cdte_track = i; else TocEntry[i].cdte_track = CDROM_LEADOUT; TocEntry[i].cdte_format = CDROM_LBA; rc=ioctl(drive,CDROMREADTOCENTRY,&TocEntry[i]); if (rc!=0) { printf("can't get TocEntry #%d (error %d).\n",i,rc); } else { lba2msf(TocEntry[i].cdte_addr.lba,&msf_ent[0]); if (TocEntry[i].cdte_track==CDROM_LEADOUT) { printf("TocEntry #%02X: %1X %1X %02d:%02d:%02d (lba: 0x%06X) %02X\n", TocEntry[i].cdte_track, TocEntry[i].cdte_adr, TocEntry[i].cdte_ctrl, msf_ent[0], msf_ent[1], msf_ent[2], TocEntry[i].cdte_addr.lba, TocEntry[i].cdte_datamode); } else { printf("TocEntry #%02d: %1X %1X %02d:%02d:%02d (lba: 0x%06X) %02X\n", TocEntry[i].cdte_track, TocEntry[i].cdte_adr, TocEntry[i].cdte_ctrl, msf_ent[0], msf_ent[1], msf_ent[2], TocEntry[i].cdte_addr.lba, TocEntry[i].cdte_datamode); } } } return (hdr.cdth_trk1); /* number of tracks */}void display(int size,unsigned char *buffer){ k=0; getchar(); for (i=0;i<(size+1)/16;i++) { printf("%4d:",i*16); for (j=0;j<16;j++) { printf(" %02X",buffer[i*16+j]); } printf(" "); for (j=0;j<16;j++) { if (isalnum(buffer[i*16+j])) printf("%c",buffer[i*16+j]); else printf("."); } printf("\n"); k++; if (k>=20) { printf("press ENTER to continue\n"); getchar(); k=0; } } } int main(){ printf("\nTesting tool for a CDROM driver's audio functions V0.1\n"); printf("(C) 1995 Eberhard Moenkeberg <emoenke@gwdg.de>\n"); printf("initializing...\n"); rc=init_drive(default_device); if (rc<0) printf("could not open %s (rc=%d).\n",default_device,rc); help(); while (1) { printf("Give a one-letter command (h = help): "); scanf("%s",command); command[1]=0; switch (command[0]) { case 'D': printf("device name (f.e. /dev/sbpcd3): ? "); scanf("%s",dev); close(drive); rc=init_drive(dev); if (rc<0) printf("could not open %s (rc %d).\n",dev,rc); break; case 'e': rc=ioctl(drive,CDROMEJECT); if (rc<0) printf("CDROMEJECT: rc=%d.\n",rc); break; case 'p': rc=ioctl(drive,CDROMPAUSE); if (rc<0) printf("CDROMPAUSE: rc=%d.\n",rc); break; case 'r': rc=ioctl(drive,CDROMRESUME); if (rc<0) printf("CDROMRESUME: rc=%d.\n",rc); break; case 's': rc=ioctl(drive,CDROMSTOP); if (rc<0) printf("CDROMSTOP: rc=%d.\n",rc); break; case 'S': rc=ioctl(drive,CDROMSTART); if (rc<0) printf("CDROMSTART: rc=%d.\n",rc); break; case 't': rc=ioctl(drive,CDROMREADTOCHDR,&tocHdr); if (rc<0) { printf("CDROMREADTOCHDR: rc=%d.\n",rc); break; } first=tocHdr.cdth_trk0; last= tocHdr.cdth_trk1; if ((first==0)||(first>last)) { printf ("--got invalid TOC data.\n"); } else { printf("--enter track number(first=%d, last=%d): ",first,last); scanf("%d",&i1); ti.cdti_trk0=i1; if (ti.cdti_trk0<first) ti.cdti_trk0=first; if (ti.cdti_trk0>last) ti.cdti_trk0=last; ti.cdti_ind0=0; ti.cdti_trk1=last; ti.cdti_ind1=0; rc=ioctl(drive,CDROMSTOP); rc=ioctl(drive,CDROMPLAYTRKIND,&ti); if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc); } break; case 'n': rc=ioctl(drive,CDROMSTOP); if (++ti.cdti_trk0>last) ti.cdti_trk0=last; ti.cdti_ind0=0; ti.cdti_trk1=last; ti.cdti_ind1=0; rc=ioctl(drive,CDROMPLAYTRKIND,&ti); if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc); break; case 'l': rc=ioctl(drive,CDROMSTOP); if (--ti.cdti_trk0<first) ti.cdti_trk0=first; ti.cdti_ind0=0; ti.cdti_trk1=last; ti.cdti_ind1=0; rc=ioctl(drive,CDROMPLAYTRKIND,&ti); if (rc<0) printf("CDROMPLAYTRKIND: rc=%d.\n",rc); break; case 'c': subchnl.cdsc_format=CDROM_MSF; rc=ioctl(drive,CDROMSUBCHNL,&subchnl); if (rc<0) printf("CDROMSUBCHNL: rc=%d.\n",rc); else { printf("AudioStatus:%s Track:%d Mode:%d MSF=%02d:%02d:%02d\n", subchnl.cdsc_audiostatus==CDROM_AUDIO_PLAY ? "PLAYING":"NOT PLAYING", subchnl.cdsc_trk,subchnl.cdsc_adr, subchnl.cdsc_absaddr.msf.minute, subchnl.cdsc_absaddr.msf.second, subchnl.cdsc_absaddr.msf.frame); } break; case 'i': printf("Track No.: "); scanf("%d",&i1); entry.cdte_track=i1; if (entry.cdte_track<first) entry.cdte_track=first; if (entry.cdte_track>last) entry.cdte_track=last; entry.cdte_format=CDROM_MSF; rc=ioctl(drive,CDROMREADTOCENTRY,&entry); if (rc<0) printf("CDROMREADTOCENTRY: rc=%d.\n",rc); else { printf("Mode %d Track, starts at %02d:%02d:%02d\n", entry.cdte_adr, entry.cdte_addr.msf.minute, entry.cdte_addr.msf.second, entry.cdte_addr.msf.frame); } break; case 'a': printf("Address (min:sec:frm) "); scanf("%d:%d:%d",&i1,&i2,&i3); msf.cdmsf_min0=i1; msf.cdmsf_sec0=i2; msf.cdmsf_frame0=i3; if (msf.cdmsf_sec0>59) msf.cdmsf_sec0=59; if (msf.cdmsf_frame0>74) msf.cdmsf_frame0=74; lba2msf(TocEntry[last+1].cdte_addr.lba-1,&msf.cdmsf_min1); rc=ioctl(drive,CDROMSTOP); rc=ioctl(drive,CDROMPLAYMSF,&msf); if (rc<0) printf("CDROMPLAYMSF: rc=%d.\n",rc); break;#ifdef AZT_PRIVATE_IOCTLS /*not supported by every CDROM driver*/ case 'd': printf("Address (min:sec:frm) "); scanf("%d:%d:%d",&i1,&i2,&i3); azt.msf.cdmsf_min0=i1; azt.msf.cdmsf_sec0=i2; azt.msf.cdmsf_frame0=i3; if (azt.msf.cdmsf_sec0>59) azt.msf.cdmsf_sec0=59; if (azt.msf.cdmsf_frame0>74) azt.msf.cdmsf_frame0=74; rc=ioctl(drive,CDROMREADMODE1,&azt.msf); if (rc<0) printf("CDROMREADMODE1: rc=%d.\n",rc); else display(CD_FRAMESIZE,azt.buf); break; case 'w': printf("Address (min:sec:frame) "); scanf("%d:%d:%d",&i1,&i2,&i3); azt.msf.cdmsf_min0=i1; azt.msf.cdmsf_sec0=i2; azt.msf.cdmsf_frame0=i3; if (azt.msf.cdmsf_sec0>59) azt.msf.cdmsf_sec0=59; if (azt.msf.cdmsf_frame0>74) azt.msf.cdmsf_frame0=74; rc=ioctl(drive,CDROMREADMODE2,&azt.msf); if (rc<0) printf("CDROMREADMODE2: rc=%d.\n",rc); else display(CD_FRAMESIZE_RAW,azt.buf); /* currently only 2336 */ break; #endif case 'v': printf("--Channel 0 (Left) (0-255): "); scanf("%d",&i1); volctrl.channel0=i1; printf("--Channel 1 (Right) (0-255): "); scanf("%d",&i1); volctrl.channel1=i1; volctrl.channel2=0; volctrl.channel3=0; rc=ioctl(drive,CDROMVOLCTRL,&volctrl); if (rc<0) printf("CDROMVOLCTRL: rc=%d.\n",rc); break; case 'q': close(drive); exit(0); case 'h': help(); break; case 'T': /* display TOC entry - without involving the driver */ scanf("%d",&i); if ((i<hdr.cdth_trk0)||(i>hdr.cdth_trk1)) printf("invalid track number.\n"); else printf("TocEntry %02d: adr=%01X ctrl=%01X msf=%02d:%02d:%02d mode=%02X\n", TocEntry[i].cdte_track, TocEntry[i].cdte_adr, TocEntry[i].cdte_ctrl, TocEntry[i].cdte_addr.msf.minute, TocEntry[i].cdte_addr.msf.second, TocEntry[i].cdte_addr.msf.frame, TocEntry[i].cdte_datamode); break; case 'A': /* read audio data into file */ printf("Address (min:sec:frm) ? "); scanf("%d:%d:%d",&i1,&i2,&i3); read_audio.addr.msf.minute=i1; read_audio.addr.msf.second=i2; read_audio.addr.msf.frame=i3; read_audio.addr_format=CDROM_MSF; printf("# of frames ? "); scanf("%d",&i1); read_audio.nframes=i1; k=read_audio.nframes*CD_FRAMESIZE_RAW; read_audio.buf= (unsigned char*) malloc(k); if (read_audio.buf==NULL) { printf("can't malloc %d bytes.\n",k); break; } sprintf(filename,"audio_%02d%02d%02d_%02d.%02d", read_audio.addr.msf.minute, read_audio.addr.msf.second, read_audio.addr.msf.frame, read_audio.nframes, ++sequence); datafile=creat(filename, 0755); if (datafile<0) { printf("can't open datafile %s.\n",filename); break; } rc=ioctl(drive,CDROMREADAUDIO,&read_audio); if (rc!=0) { printf("CDROMREADAUDIO: rc=%d.\n",rc); } else { rc=write(datafile,&read_audio.buf,k); if (rc!=k) printf("datafile I/O error (%d).\n",rc); } close(datafile); break; case 'X': /* set EJECT_SW (0: disable, 1: enable auto-ejecting) */ scanf("%d",&i); rc=ioctl(drive,CDROMEJECT_SW,i); if (rc!=0) printf("CDROMEJECT_SW: rc=%d.\n",rc); else printf("EJECT_SW set to %d\n",i); break; case 'M': /* get the multisession redirection info */ ms_info.addr_format=CDROM_LBA; rc=ioctl(drive,CDROMMULTISESSION,&ms_info); if (rc!=0) { printf("CDROMMULTISESSION(lba): rc=%d.\n",rc); } else { if (ms_info.xa_flag) printf("MultiSession offset (lba): %d (0x%06X)\n",ms_info.addr.lba,ms_info.addr.lba); else { printf("this CD is not an XA disk.\n"); break; } } ms_info.addr_format=CDROM_MSF; rc=ioctl(drive,CDROMMULTISESSION,&ms_info); if (rc!=0) { printf("CDROMMULTISESSION(msf): rc=%d.\n",rc); } else { if (ms_info.xa_flag) printf("MultiSession offset (msf): %02d:%02d:%02d (0x%02X%02X%02X)\n", ms_info.addr.msf.minute, ms_info.addr.msf.second, ms_info.addr.msf.frame, ms_info.addr.msf.minute, ms_info.addr.msf.second, ms_info.addr.msf.frame); else printf("this CD is not an XA disk.\n"); } break;#ifdef SBP_PRIVATE_IOCTLS case 'Y': /* set the driver's message level */#if 0 /* not implemented yet */ printf("enter switch name (f.e. DBG_CMD): "); scanf("%s",&dbg_switch); j=get_dbg_num(dbg_switch);#else printf("enter DDIOCSDBG switch number: "); scanf("%d",&j);#endif printf("enter 0 for \"off\", 1 for \"on\": "); scanf("%d",&i); if (i==0) j|=0x80; printf("calling \"ioctl(drive,DDIOCSDBG,%d)\"\n",j); rc=ioctl(drive,DDIOCSDBG,j); printf("DDIOCSDBG: rc=%d.\n",rc); break; case 'Z': /* set the audio buffer size */ printf("# frames wanted: ? "); scanf("%d",&j); rc=ioctl(drive,CDROMAUDIOBUFSIZ,j); printf("%d frames granted.\n",rc); break; case 'V': rc=ioctl(drive,CDROMVOLREAD,&volctrl); if (rc<0) printf("CDROMVOLCTRL: rc=%d.\n",rc); printf("Volume: channel 0 (left) %d, channel 1 (right) %d\n",volctrl.channel0,volctrl.channel1); break; case 'R': rc=ioctl(drive,CDROMRESET); if (rc<0) printf("CDROMRESET: rc=%d.\n",rc); break; case 'B': /* set the driver's (?) read ahead value */ printf("enter read-ahead size: ? "); scanf("%d",&i); rc=ioctl(drive,BLKRASET,i); if (rc<0) printf("BLKRASET: rc=%d.\n",rc); break;#endif SBP_PRIVATE_IOCTLS default: printf("unknown command: \"%s\".\n",command); break; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -