📄 scsi_mmc.c
字号:
if (0 == i_status) { uint8_t *p; uint8_t *p_max = buf + 256; *p_read_cap = 0; *p_write_cap = 0; *p_misc_cap = 0; /* set to first sense mask, and then walk through the masks */ p = buf + 8; while( (p < &(buf[2+i_data])) && (p < p_max) ) { uint8_t which_page; which_page = p[0] & 0x3F; switch( which_page ) { case CDIO_MMC_AUDIO_CTL_PAGE: case CDIO_MMC_R_W_ERROR_PAGE: case CDIO_MMC_CDR_PARMS_PAGE: /* Don't handle these yet. */ break; case CDIO_MMC_CAPABILITIES_PAGE: scsi_mmc_get_drive_cap_buf(p, p_read_cap, p_write_cap, p_misc_cap); break; default: ; } p += (p[1] + 2); } } else { cdio_info("%s: %s\n", "error in MODE_SELECT", strerror(errno)); *p_read_cap = CDIO_DRIVE_CAP_ERROR; *p_write_cap = CDIO_DRIVE_CAP_ERROR; *p_misc_cap = CDIO_DRIVE_CAP_ERROR; } return;}voidscsi_mmc_get_drive_cap (const CdIo *p_cdio, /*out*/ cdio_drive_read_cap_t *p_read_cap, /*out*/ cdio_drive_write_cap_t *p_write_cap, /*out*/ cdio_drive_misc_cap_t *p_misc_cap){ if ( ! p_cdio ) return; scsi_mmc_get_drive_cap_private (p_cdio->env, p_cdio->op.run_scsi_mmc_cmd, p_read_cap, p_write_cap, p_misc_cap);}voidscsi_mmc_get_drive_cap_generic (const void *p_user_data, /*out*/ cdio_drive_read_cap_t *p_read_cap, /*out*/ cdio_drive_write_cap_t *p_write_cap, /*out*/ cdio_drive_misc_cap_t *p_misc_cap){ const generic_img_private_t *p_env = p_user_data; scsi_mmc_get_drive_cap( p_env->cdio, p_read_cap, p_write_cap, p_misc_cap );}/*! Get the DVD type associated with cd object.*/discmode_tscsi_mmc_get_dvd_struct_physical_private ( void *p_env, const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, cdio_dvd_struct_t *s){ scsi_mmc_cdb_t cdb = {{0, }}; unsigned char buf[4 + 4 * 20], *base; int i_status; uint8_t layer_num = s->physical.layer_num; cdio_dvd_layer_t *layer; if ( ! p_env || ! run_scsi_mmc_cmd ) return -2; if (layer_num >= CDIO_DVD_MAX_LAYERS) return -EINVAL; CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_DVD_STRUCTURE); cdb.field[6] = layer_num; cdb.field[7] = CDIO_DVD_STRUCT_PHYSICAL; cdb.field[9] = sizeof(buf) & 0xff; i_status = run_scsi_mmc_cmd(p_env, DEFAULT_TIMEOUT_MS, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_READ, sizeof(buf), &buf); if (0 != i_status) return CDIO_DISC_MODE_ERROR; base = &buf[4]; layer = &s->physical.layer[layer_num]; /* * place the data... really ugly, but at least we won't have to * worry about endianess in userspace. */ memset(layer, 0, sizeof(*layer)); layer->book_version = base[0] & 0xf; layer->book_type = base[0] >> 4; layer->min_rate = base[1] & 0xf; layer->disc_size = base[1] >> 4; layer->layer_type = base[2] & 0xf; layer->track_path = (base[2] >> 4) & 1; layer->nlayers = (base[2] >> 5) & 3; layer->track_density = base[3] & 0xf; layer->linear_density = base[3] >> 4; layer->start_sector = base[5] << 16 | base[6] << 8 | base[7]; layer->end_sector = base[9] << 16 | base[10] << 8 | base[11]; layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15]; layer->bca = base[16] >> 7; return 0;}/*! Get the DVD type associated with cd object.*/discmode_tscsi_mmc_get_dvd_struct_physical ( const CdIo *p_cdio, cdio_dvd_struct_t *s){ if ( ! p_cdio ) return -2; return scsi_mmc_get_dvd_struct_physical_private (p_cdio->env, p_cdio->op.run_scsi_mmc_cmd, s);}/*! Get the CD-ROM hardware info via a SCSI MMC INQUIRY command. False is returned if we had an error getting the information.*/bool scsi_mmc_get_hwinfo ( const CdIo *p_cdio, /*out*/ cdio_hwinfo_t *hw_info ){ int i_status; /* Result of SCSI MMC command */ char buf[36] = { 0, }; /* Place to hold returned data */ scsi_mmc_cdb_t cdb = {{0, }}; /* Command Descriptor Block */ CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_INQUIRY); cdb.field[4] = sizeof(buf); if (! p_cdio || ! hw_info ) return false; i_status = scsi_mmc_run_cmd(p_cdio, DEFAULT_TIMEOUT_MS, &cdb, SCSI_MMC_DATA_READ, sizeof(buf), &buf); if (i_status == 0) { memcpy(hw_info->psz_vendor, buf + 8, sizeof(hw_info->psz_vendor)-1); hw_info->psz_vendor[sizeof(hw_info->psz_vendor)-1] = '\0'; memcpy(hw_info->psz_model, buf + 8 + CDIO_MMC_HW_VENDOR_LEN, sizeof(hw_info->psz_model)-1); hw_info->psz_model[sizeof(hw_info->psz_model)-1] = '\0'; memcpy(hw_info->psz_revision, buf + 8 + CDIO_MMC_HW_VENDOR_LEN + CDIO_MMC_HW_MODEL_LEN, sizeof(hw_info->psz_revision)-1); hw_info->psz_revision[sizeof(hw_info->psz_revision)-1] = '\0'; return true; } return false;}/*! Return the media catalog number MCN. Note: string is malloc'd so caller should free() then returned string when done with it. */char *scsi_mmc_get_mcn_private ( void *p_env, const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd ){ scsi_mmc_cdb_t cdb = {{0, }}; char buf[28] = { 0, }; int i_status; if ( ! p_env || ! run_scsi_mmc_cmd ) return NULL; CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_SUBCHANNEL); cdb.field[1] = 0x0; cdb.field[2] = 0x40; cdb.field[3] = CDIO_SUBCHANNEL_MEDIA_CATALOG; CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(buf)); i_status = run_scsi_mmc_cmd(p_env, DEFAULT_TIMEOUT_MS, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_READ, sizeof(buf), buf); if(i_status == 0) { return strdup(&buf[9]); } return NULL;}char *scsi_mmc_get_mcn ( const CdIo *p_cdio ){ if ( ! p_cdio ) return NULL; return scsi_mmc_get_mcn_private (p_cdio->env, p_cdio->op.run_scsi_mmc_cmd );}char *scsi_mmc_get_mcn_generic (const void *p_user_data){ const generic_img_private_t *p_env = p_user_data; return scsi_mmc_get_mcn( p_env->cdio );}/* Read cdtext information for a CdIo object . return true on success, false on error or CD-Text information does not exist.*/boolscsi_mmc_init_cdtext_private ( void *p_user_data, const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, set_cdtext_field_fn_t set_cdtext_field_fn ){ generic_img_private_t *p_env = p_user_data; scsi_mmc_cdb_t cdb = {{0, }}; unsigned char wdata[5000] = { 0, }; int i_status, i_errno; if ( ! p_env || ! run_scsi_mmc_cmd || p_env->b_cdtext_error ) return false; /* Operation code */ CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); cdb.field[1] = CDIO_CDROM_MSF; /* Format */ cdb.field[2] = CDIO_MMC_READTOC_FMT_CDTEXT; /* Setup to read header, to get length of data */ CDIO_MMC_SET_READ_LENGTH16(cdb.field, 4); errno = 0;/* Set read timeout 3 minues. */#define READ_TIMEOUT 3*60*1000 /* We may need to give CD-Text a little more time to complete. */ /* First off, just try and read the size */ i_status = run_scsi_mmc_cmd (p_env, READ_TIMEOUT, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_READ, 4, &wdata); if (i_status != 0) { cdio_info ("CD-Text read failed for header: %s\n", strerror(errno)); i_errno = errno; p_env->b_cdtext_error = true; return false; } else { /* Now read the CD-Text data */ int i_cdtext = CDIO_MMC_GET_LEN16(wdata); if (i_cdtext > sizeof(wdata)) i_cdtext = sizeof(wdata); CDIO_MMC_SET_READ_LENGTH16(cdb.field, i_cdtext); i_status = run_scsi_mmc_cmd (p_env, READ_TIMEOUT, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_READ, i_cdtext, &wdata); if (i_status != 0) { cdio_info ("CD-Text read for text failed: %s\n", strerror(errno)); i_errno = errno; p_env->b_cdtext_error = true; return false; } p_env->b_cdtext_init = true; return cdtext_data_init(p_env, p_env->i_first_track, wdata, set_cdtext_field_fn); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -