📄 _cdio_linux.c
字号:
/*! Eject media in CD drive. Return 0 if success and 1 for failure, and 2 if no routine. */static int eject_media_linux (void *p_user_data) { _img_private_t *p_env = p_user_data; int ret=2; int status; int fd; if ((fd = open (p_env->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) { if((status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) > 0) { switch(status) { case CDS_TRAY_OPEN: if((ret = ioctl(fd, CDROMCLOSETRAY)) != 0) { cdio_warn ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno)); ret = 1; } break; case CDS_DISC_OK: if((ret = ioctl(fd, CDROMEJECT)) != 0) { int eject_error = errno; /* Try ejecting the MMC way... */ ret = scsi_mmc_eject_media(p_env->gen.cdio); if (0 != ret) { cdio_warn("ioctl CDROMEJECT failed: %s\n", strerror(eject_error)); ret = 1; } } /* force kernel to reread partition table when new disc inserted */ ret = ioctl(p_env->gen.fd, BLKRRPART); break; default: cdio_warn ("Unknown CD-ROM (%d)\n", status); ret = 1; } } else { cdio_warn ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)); ret=1; } close(fd); } else ret = 2; close(p_env->gen.fd); p_env->gen.fd = -1; return ret;}/*! Get disc type associated with the cd object.*/static discmode_tget_discmode_linux (void *p_user_data){ _img_private_t *p_env = p_user_data; int32_t i_discmode; /* See if this is a DVD. */ cdio_dvd_struct_t dvd; /* DVD READ STRUCT for layer 0. */ dvd.physical.type = CDIO_DVD_STRUCT_PHYSICAL; dvd.physical.layer_num = 0; if (0 == ioctl (p_env->gen.fd, DVD_READ_STRUCT, &dvd)) { switch(dvd.physical.layer[0].book_type) { case CDIO_DVD_BOOK_DVD_ROM: return CDIO_DISC_MODE_DVD_ROM; case CDIO_DVD_BOOK_DVD_RAM: return CDIO_DISC_MODE_DVD_RAM; case CDIO_DVD_BOOK_DVD_R: return CDIO_DISC_MODE_DVD_R; case CDIO_DVD_BOOK_DVD_RW: return CDIO_DISC_MODE_DVD_RW; case CDIO_DVD_BOOK_DVD_PR: return CDIO_DISC_MODE_DVD_PR; case CDIO_DVD_BOOK_DVD_PRW: return CDIO_DISC_MODE_DVD_PRW; default: return CDIO_DISC_MODE_DVD_OTHER; } } i_discmode = ioctl (p_env->gen.fd, CDROM_DISC_STATUS); if (i_discmode < 0) return CDIO_DISC_MODE_ERROR; /* FIXME Need to add getting DVD types. */ switch(i_discmode) { case CDS_AUDIO: return CDIO_DISC_MODE_CD_DA; case CDS_DATA_1: case CDS_DATA_2: return CDIO_DISC_MODE_CD_DATA; case CDS_MIXED: return CDIO_DISC_MODE_CD_MIXED; case CDS_XA_2_1: case CDS_XA_2_2: return CDIO_DISC_MODE_CD_XA; case CDS_NO_INFO: return CDIO_DISC_MODE_NO_INFO; default: return CDIO_DISC_MODE_ERROR; }}/* Check a drive to see if it is a CD-ROM Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive and -1 if no device exists .*/static boolis_cdrom_linux(const char *drive, char *mnttype){ bool is_cd=false; int cdfd; struct cdrom_tochdr tochdr; /* If it doesn't exist, return -1 */ if ( !cdio_is_device_quiet_generic(drive) ) { return(false); } /* If it does exist, verify that it's an available CD-ROM */ cdfd = open(drive, (O_RDONLY|O_NONBLOCK), 0); if ( cdfd >= 0 ) { if ( ioctl(cdfd, CDROMREADTOCHDR, &tochdr) != -1 ) { is_cd = true; } close(cdfd); } /* Even if we can't read it, it might be mounted */ else if ( mnttype && (strcmp(mnttype, "iso9660") == 0) ) { is_cd = true; } return(is_cd);}/* MMC driver to read audio sectors. Can read only up to 25 blocks.*/static int_read_audio_sectors_linux (void *p_user_data, void *buf, lsn_t lsn, unsigned int nblocks){ _img_private_t *p_env = p_user_data; return scsi_mmc_read_sectors( p_env->gen.cdio, buf, lsn, CDIO_MMC_READ_TYPE_CDDA, nblocks);}/* Packet driver to read mode2 sectors. Can read only up to 25 blocks.*/static int_read_mode2_sectors_mmc (_img_private_t *p_env, void *p_buf, lba_t lba, unsigned int nblocks, bool b_read_10){ scsi_mmc_cdb_t cdb = {{0, }}; CDIO_MMC_SET_READ_LBA(cdb.field, lba); if (b_read_10) { int retval; CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_10); CDIO_MMC_SET_READ_LENGTH16(cdb.field, nblocks); if ((retval = scsi_mmc_set_blocksize (p_env->gen.cdio, M2RAW_SECTOR_SIZE))) return retval; if ((retval = run_scsi_cmd_linux (p_env, 0, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_READ, M2RAW_SECTOR_SIZE * nblocks, p_buf))) { scsi_mmc_set_blocksize (p_env->gen.cdio, CDIO_CD_FRAMESIZE); return retval; } if ((retval = scsi_mmc_set_blocksize (p_env->gen.cdio, CDIO_CD_FRAMESIZE))) return retval; } else cdb.field[1] = 0; /* sector size mode2 */ cdb.field[9] = 0x58; /* 2336 mode2 */ CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_CD); CDIO_MMC_SET_READ_LENGTH24(cdb.field, nblocks); return run_scsi_cmd_linux (p_env, 0, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_READ, M2RAW_SECTOR_SIZE * nblocks, p_buf); return 0;}static int_read_mode2_sectors (_img_private_t *p_env, void *p_buf, lba_t lba, unsigned int nblocks, bool b_read_10){ unsigned int l = 0; int retval = 0; while (nblocks > 0) { const unsigned nblocks2 = (nblocks > 25) ? 25 : nblocks; void *p_buf2 = ((char *)p_buf ) + (l * M2RAW_SECTOR_SIZE); retval |= _read_mode2_sectors_mmc (p_env, p_buf2, lba + l, nblocks2, b_read_10); if (retval) break; nblocks -= nblocks2; l += nblocks2; } return retval;}/*! Reads a single mode1 sector from cd device into data starting from lsn. Returns 0 if no error. */static int_read_mode1_sector_linux (void *p_user_data, void *p_data, lsn_t lsn, bool b_form2){#if FIXED char buf[M2RAW_SECTOR_SIZE] = { 0, }; struct cdrom_msf *p_msf = (struct cdrom_msf *) &buf; msf_t _msf; _img_private_t *p_env = p_user_data; cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf); msf->cdmsf_min0 = cdio_from_bcd8(_msf.m); msf->cdmsf_sec0 = cdio_from_bcd8(_msf.s); msf->cdmsf_frame0 = cdio_from_bcd8(_msf.f); retry: switch (p_env->access_mode) { case _AM_NONE: cdio_warn ("no way to read mode1"); return 1; break; case _AM_IOCTL: if (ioctl (p_env->gen.fd, CDROMREADMODE1, &buf) == -1) { perror ("ioctl()"); return 1; /* exit (EXIT_FAILURE); */ } break; case _AM_READ_CD: case _AM_READ_10: if (_read_mode2_sectors (p_env->gen.fd, buf, lsn, 1, (p_env->access_mode == _AM_READ_10))) { perror ("ioctl()"); if (p_env->access_mode == _AM_READ_CD) { cdio_info ("READ_CD failed; switching to READ_10 mode..."); p_env->access_mode = _AM_READ_10; goto retry; } else { cdio_info ("READ_10 failed; switching to ioctl(CDROMREADMODE2) mode..."); p_env->access_mode = _AM_IOCTL; goto retry; } return 1; } break; } memcpy (data, buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE, b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); #else return cdio_generic_read_form1_sector(p_user_data, p_data, lsn);#endif return 0;}/*! Reads nblocks of mode2 sectors from cd device into data starting from lsn. Returns 0 if no error. */static int_read_mode1_sectors_linux (void *p_user_data, void *p_data, lsn_t lsn, bool b_form2, unsigned int nblocks){ _img_private_t *p_env = p_user_data; unsigned int i; int retval; unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; for (i = 0; i < nblocks; i++) { if ( (retval = _read_mode1_sector_linux (p_env, ((char *)p_data) + (blocksize*i), lsn + i, b_form2)) ) return retval; } return 0;}/*! Reads a single mode2 sector from cd device into data starting from lsn. Returns 0 if no error. */static int_read_mode2_sector_linux (void *p_user_data, void *p_data, lsn_t lsn, bool b_form2){ char buf[M2RAW_SECTOR_SIZE] = { 0, }; struct cdrom_msf *msf = (struct cdrom_msf *) &buf; msf_t _msf; _img_private_t *p_env = p_user_data; cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf); msf->cdmsf_min0 = cdio_from_bcd8(_msf.m); msf->cdmsf_sec0 = cdio_from_bcd8(_msf.s); msf->cdmsf_frame0 = cdio_from_bcd8(_msf.f); retry: switch (p_env->access_mode) { case _AM_NONE: cdio_warn ("no way to read mode2"); return 1; break; case _AM_IOCTL: if (ioctl (p_env->gen.fd, CDROMREADMODE2, &buf) == -1) { perror ("ioctl()"); return 1; /* exit (EXIT_FAILURE); */ } break; case _AM_READ_CD: case _AM_READ_10: if (_read_mode2_sectors (p_env, buf, lsn, 1, (p_env->access_mode == _AM_READ_10))) { perror ("ioctl()"); if (p_env->access_mode == _AM_READ_CD) { cdio_info ("READ_CD failed; switching to READ_10 mode..."); p_env->access_mode = _AM_READ_10; goto retry; } else { cdio_info ("READ_10 failed; switching to ioctl(CDROMREADMODE2) mode..."); p_env->access_mode = _AM_IOCTL; goto retry; } return 1; } break; } if (b_form2) memcpy (p_data, buf, M2RAW_SECTOR_SIZE); else memcpy (((char *)p_data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); return 0;}/*! Reads nblocks of mode2 sectors from cd device into data starting from lsn. Returns 0 if no error. */static int_read_mode2_sectors_linux (void *p_user_data, void *data, lsn_t lsn, bool b_form2, unsigned int nblocks){ _img_private_t *p_env = p_user_data; unsigned int i; unsigned int i_blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; /* For each frame, pick out the data part we need */ for (i = 0; i < nblocks; i++) { int retval; if ( (retval = _read_mode2_sector_linux (p_env, ((char *)data) + (i_blocksize*i), lsn + i, b_form2)) ) return retval; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -