📄 cdtest.c
字号:
* expected data, if CD type is known. */read_data_track(toc)struct cdrom_tocentry *toc;{ struct datacon_info *info; int lba, start, end, blocksize, nblk, maxnblk, k; int *mark; info = cd_datacon[cd_type]; blocksize = toc->cdte_datamode == CD_DATAMODE1 ? CDROM_MODE1_SIZE : CDROM_MODE2_SIZE; maxnblk = MAX_DATABUF / blocksize; start = toc->cdte_addr.lba; /* first logical block */ end = (toc+1)->cdte_addr.lba - 1; /* last logical block */ /* skip gaps between certain tracks */ if (toc->cdte_track != tochdr.cdth_trk1) { /* * if data mode 1 then skip gaps on all but the last track, * if data mode 2 then skip only if the next track is audio. */ if (toc->cdte_datamode == CD_DATAMODE1) end -= CD_POSTGAP; else { if (!((toc+1)->cdte_ctrl & CDTRK_DATA)) end -= CD_POSTGAP; } } if (end < start) return; send_message(NULL,VDEBUG,"Read CD track %d (data mode %d, %d blocks)", toc->cdte_track,toc->cdte_datamode,(end-start+1)*percent_data/100); /* if CD type is known then read and compare data of first block */ if (cd_type != CD_OTHER) { /* searching for the expected track data in table */ while (info->track != toc->cdte_track && info->track != CDROM_LEADOUT) info++; /* if found then read and compare the beginning data stream */ if (info->track == toc->cdte_track) { nblk = info->size / blocksize; if (info->size % blocksize) nblk++; send_message(NULL,VDEBUG,"Read block %d and compare %d bytes of data",start,info->size); read_data_blocks(toc->cdte_datamode,start,nblk,blocksize); if (bcmp(databuf,info->expect,info->size)) send_message(ERDATA,ERROR,er_datacmp,info->size,start); } } /* * This condition allows testing a partial number of data blocks in * a track by changing the start and end logical block addresses. */ if (percent_data < 100) { k = end - start + 1; nblk = k * percent_data / 100;# ifdef SVR4 lba = abs((int)rand());# else lba = abs((int)random());# endif SVR4 lba %= (k - nblk + 1); start += lba; end = start + nblk - 1; } if (read_access == RANDOM_READ) { send_message(NULL,VDEBUG,"Randomly read block %d thru %d",start,end); /* allocate memory to maintain read/unread block mark */ k = (end - start) / 8 + 8; if (!(mark = (int *)malloc((u_int)k))) send_message(ERSYS,ERROR,er_mem,k); bzero((char *)mark,k); /* randomly read all blocks once */ for (k = start; k <= end; k += nblk) { lba = rnd_blkpos(mark,start,end); nblk = rnd_blkcnt(mark,start,end,lba,maxnblk); read_data_blocks(toc->cdte_datamode,lba,nblk,blocksize); /* if quick test then only read one chunk */ if (quick_test) break; } /* free mark memory */ free((char *)mark); } else { send_message(NULL,VDEBUG,"Sequentially read block %d thru %d",start,end); /* sequential read all blocks once */ for (lba = start; lba <= end; lba += nblk) {# ifdef SVR4 nblk = abs((int)rand());# else nblk = abs((int)random());# endif SVR4 nblk = (nblk % maxnblk) + 1; if (nblk > (end - lba + 1)) nblk = end - lba + 1; read_data_blocks(toc->cdte_datamode,lba,nblk,blocksize); /* if quick test then only read one chunk */ if (quick_test) break; } }}/* * Function to read number of blocks at specified logical block address. */read_data_blocks(datamode,lba,nblk,blocksize)u_char datamode;int lba, nblk, blocksize;{ struct cdrom_read readinfo; int size; send_message(NULL,DEBUG,"Read block %d thru %d, block size %d", lba,lba+nblk-1,blocksize); switch (datamode) { case CD_DATAMODE1: /* CD data mode 1 can be read with normal read */ size = nblk * blocksize; if (lseek(fd,(long)(lba*blocksize),L_SET) == -1) send_message(ERSEEK,ERROR,er_seek,lba,errmsg(errno)); if (read(fd,databuf,size) != size) send_message(ERREAD,ERROR,er_read,size,lba,errmsg(errno)); break; case CD_DATAMODE2: /* CD data mode 2 can only be read thru special ioctl */ size = nblk * blocksize; readinfo.cdread_lba = lba; readinfo.cdread_bufaddr = databuf; readinfo.cdread_buflen = size; if (ioctl(fd,CDROMREADMODE2,&readinfo) < 0) send_message(ERREAD,ERROR,er_read,size,lba,errmsg(errno)); break; default: send_message(ERREAD,ERROR,er_datamode,datamode); break; }}/* * Function returns a random logical block address that has not yet been read, * where mark is the bit stream indicating blocks that are read/unread, start * and end are the first and last block boundaries. Function will also mark * the bit position that is selected as being read. * * Note that, rnd_blkpos() and rnd_blkcnt() are used to randomly select * all blocks, each time a random number of blocks, and each block will * be selected once. */rnd_blkpos(mark,start,end)int *mark, start, end;{ u_int count, index, bit, pos; /* select logical block within 0 and end-start+1 boundaries */ count = end - start + 1;# ifdef SVR4 randval = (u_int)rand();# else randval = (u_int)random();# endif SVR4 pos = randval % count; /* check if block has been read then use the next unread ones */ for (;;) { index = pos >> 5; bit = pos & 31; if (!((1 << bit) & mark[index])) break; if (++pos >= count) pos = 0; } mark[index] |= (1 << bit); /* return the random position with offset from start */ return(pos+start);}/* * Function returns a random number of contiguous blocks that are not read, * where mark is the bit stream indicating blocks that are read/unread, start * and end are the first and last logical block boundaries, lba is the current * logical block, and maxnblk is the maximum number of blocks expected to * return. Function will also mark the returned number of bits following * bit position from lba as being read. * * Note that, rnd_blkpos() and rnd_blkcnt() are used to randomly select * all blocks, each time a random number of blocks, and each block will * be selected once. */rnd_blkcnt(mark,start,end,lba,maxnblk)int *mark, start, end, lba, maxnblk;{ u_int nblk, count, index, bit; /* select random number of blocks based on max number of blocks */ if ((lba + maxnblk) > end) maxnblk = end - lba + 1; count = (randval % maxnblk) + 1; /* adjust random number of blocks to contiguous unread blocks */ lba -= start; for (nblk = 1; nblk < count; nblk++) { lba++; index = lba >> 5; bit = lba & 31; if ((1 << bit) & mark[index]) return(nblk); mark[index] |= (1 << bit); } return(count);}/* * Function to play specified audio track. * The audio status will be checked during audio play, and a time limit * will be set for each track play according to the TOC information. */play_audio_track(toc)struct cdrom_tocentry *toc;{ struct cdrom_ti ti; struct cdrom_subchnl subchnl; struct cdrom_volctrl volctrl; u_long timelimit, timestart, timeout; struct timeval t; timelimit = ((toc+1)->cdte_addr.lba - toc->cdte_addr.lba) / NBLOCKS_SEC; send_message(NULL,DEBUG,"Play CD track %d (%d seconds)",toc->cdte_track,timelimit); /* Add extra seconds for error recovery: Hai 10/24/90 */ /* Change 45 sec to 60 to avoid unnecessary restriction during */ /* heavy system load on scsi bus. Patrick 7/24/90 */ timeout = timelimit + 600; /* Add timeout for play fatal */ timelimit += 60 ; /* set audio volume control */ volctrl.channel0 = volctrl.channel1 = audio_volume; volctrl.channel2 = volctrl.channel3 = audio_volume; if (ioctl(fd,CDROMVOLCTRL,&volctrl) < 0) send_message(ERIOCTL,ERROR,er_ioctl,"CDROMVOLCTRL",errmsg(errno)); /* play audio track/index */ ti.cdti_trk0 = ti.cdti_trk1 = toc->cdte_track; ti.cdti_ind0 = ti.cdti_ind1 = MIN_INDEX; if (ioctl(fd,CDROMPLAYTRKIND,&ti) < 0) send_message(ERIOCTL,ERROR,er_ioctl,"CDROMPLAYTRKIND",errmsg(errno)); /* if quick test then don't need to check audio status */ if (quick_test) return; /* wait while audio is still playing */ (void) gettimeofday(&t,(struct timezone *)0); timestart = t.tv_sec; do { (void) gettimeofday(&t,(struct timezone *)0); sleep(3); if (ioctl(fd,CDROMSUBCHNL,&subchnl) < 0) send_message(ERIOCTL,ERROR,er_ioctl,"CDROMSUBCHNL",errmsg(errno)); if (subchnl.cdsc_audiostatus != CDROM_AUDIO_PLAY) break; } while ((t.tv_sec - timestart) <= timeout); /* check the audio status received */ switch (subchnl.cdsc_audiostatus) { case CDROM_AUDIO_COMPLETED: /* completion ok */ if((t.tv_sec - timestart) > timelimit) send_message(0, INFO, warn_play, t.tv_sec-timestart, timelimit, ti.cdti_trk0); break; case CDROM_AUDIO_PLAY: /* still play after time out */ send_message(ERSTATUS,ERROR,er_audioplay,timeout,ti.cdti_trk0); break; case CDROM_AUDIO_PAUSED: /* pause before complete */ send_message(ERSTATUS,ERROR,er_audiostop,ti.cdti_trk0); break; case CDROM_AUDIO_ERROR: /* error during play */ send_message(ERSTATUS,ERROR,er_audioerr,ti.cdti_trk0); break; case CDROM_AUDIO_NO_STATUS: /* no status to return */ break; default: /* unknown audio status */ send_message(ERSTATUS,ERROR,er_audiostat, subchnl.cdsc_audiostatus,ti.cdti_trk0); break; }}/* * Dummy clean up as required by libsdrtns.a */clean_up(){ if (cdtoc) free((char *)cdtoc); if (databuf) free(databuf); if (fd > 0) { (void)ioctl(fd,CDROMSTOP); (void)close(fd); }}/******************************************************************************/#ifdef lintint errno;int quick_test;char *device_name;char *versionid;/* VARARGS0 */void send_message(){}#endif/******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -