コード例 #1
0
ファイル: win32_ioctl.c プロジェクト: Crome/libcdio
/*! 
  Read and cache the CD's Track Table of Contents and track info.
  Return true if successful or false if an error.
*/
bool
read_toc_win32ioctl (_img_private_t *p_env) 
{
  CDROM_TOC    cdrom_toc;
  DWORD        dw_bytes_returned;
  unsigned int i, j;
  bool         b_fulltoc_first;  /* Do we do fulltoc or DeviceIoControl 
				    first? */
  if ( ! p_env ) return false;

  /* 
     The MMC5 spec says:
       For media other than CD, information may be fabricated in order
                                            ^^^ ^^
       to emulate a CD structure for the specific media.

     There is no requirement though that it *has* to and some DVD
     drives like one by Thompson for XBOX don't support a
     IOCTL_CDROM_READ_TOC for DVD's. So if we have a DVD we should not
     prefer getting the TOC via MMC.

     But on the other hand in GNU/Linux it is reported that using the
     TOC via MMC gives better information such as for CD DATA Form 2 (used
     in SVCDs). So if we *don't* have a DVD I think we want to try MMC
     first. 

     Is this complicated enough? I could be wrong...

   */
  b_fulltoc_first = (CDIO_DISC_MODE_NO_INFO == dvd_discmode_win32ioctl(p_env));

  if ( b_fulltoc_first && read_fulltoc_win32mmc(p_env) ) return true;

  /* SCSI-MMC READ_TOC (FULTOC) read failed or we don't want to try it
     initiaily.  Try reading TOC via DeviceIoControl... */

  if( DeviceIoControl( p_env->h_device_handle,
		       IOCTL_CDROM_READ_TOC,
		       NULL, 0, &cdrom_toc, sizeof(CDROM_TOC),
		       &dw_bytes_returned, NULL ) == 0 ) {
    char *psz_msg = NULL;
    long int i_err = GetLastError();
    cdio_log_level_t loglevel = b_fulltoc_first 
      ? CDIO_LOG_WARN : CDIO_LOG_DEBUG;

    FORMAT_ERROR(i_err, psz_msg);
    if (psz_msg) {
      cdio_log(loglevel, "could not read TOC (%ld): %s", i_err, psz_msg);
      LocalFree(psz_msg);
    } else 
      cdio_log(loglevel, "could not read TOC (%ld)", i_err);

    if ( !b_fulltoc_first && read_fulltoc_win32mmc(p_env) ) return true;
    return false;
  }
  
  p_env->gen.i_first_track = cdrom_toc.FirstTrack;
  p_env->gen.i_tracks  = cdrom_toc.LastTrack - cdrom_toc.FirstTrack + 1;

  j = p_env->gen.i_first_track;
  for( i = 0 ; i <= p_env->gen.i_tracks ; i++, j++ ) {
    p_env->tocent[ i ].start_lsn = 
      cdio_lba_to_lsn(
		      cdio_msf3_to_lba( cdrom_toc.TrackData[i].Address[1],
					cdrom_toc.TrackData[i].Address[2],
					cdrom_toc.TrackData[i].Address[3] )
		      );
    p_env->tocent[i].Control   = cdrom_toc.TrackData[i].Control;
    p_env->tocent[i].Format    = cdrom_toc.TrackData[i].Adr;

    p_env->gen.track_flags[j].preemphasis = 
      p_env->tocent[i].Control & 0x1 
      ? CDIO_TRACK_FLAG_TRUE : CDIO_TRACK_FLAG_FALSE;

    p_env->gen.track_flags[j].copy_permit = 
      p_env->tocent[i].Control & 0x2 
      ? CDIO_TRACK_FLAG_TRUE : CDIO_TRACK_FLAG_FALSE;
    
    p_env->gen.track_flags[j].channels = 
      p_env->tocent[i].Control & 0x8 ? 4 : 2;
    

    cdio_debug("p_sectors: %i, %lu", i, 
	       (unsigned long int) (p_env->tocent[i].start_lsn));
  }
  p_env->gen.toc_init = true;
  return true;
}
コード例 #2
0
ファイル: sector.c プロジェクト: 3aychonok/libcdio
/*!
  Convert a string of the form MM:SS:FF into the corresponding LBA.
  CDIO_INVALID_LBA is returned if there is an error.
*/
lba_t
cdio_mmssff_to_lba (const char *psz_mmssff)
{
  int psz_field;
  lba_t ret;
  unsigned char c;

  if (0 == strcmp (psz_mmssff, "0"))
    return 0;

  c = *psz_mmssff++;
  if(c >= '0' && c <= '9')
    psz_field = (c - '0');
  else
    return CDIO_INVALID_LBA;
  while(':' != (c = *psz_mmssff++)) {
    if(c >= '0' && c <= '9')
      psz_field = psz_field * 10 + (c - '0');
    else
      return CDIO_INVALID_LBA;
  }

  ret = cdio_msf3_to_lba (psz_field, 0, 0);

  c = *psz_mmssff++;
  if(c >= '0' && c <= '9')
    psz_field = (c - '0');
  else
    return CDIO_INVALID_LBA;
  if(':' != (c = *psz_mmssff++)) {
    if(c >= '0' && c <= '9') {
      psz_field = psz_field * 10 + (c - '0');
      c = *psz_mmssff++;
      if(c != ':')
	return CDIO_INVALID_LBA;
    }
    else
      return CDIO_INVALID_LBA;
  }

  if(psz_field >= CDIO_CD_SECS_PER_MIN)
    return CDIO_INVALID_LBA;

  ret += cdio_msf3_to_lba (0, psz_field, 0);

  c = *psz_mmssff++;
  if (isdigit(c))
    psz_field = (c - '0');
  else
    return -1;
  if('\0' != (c = *psz_mmssff++)) {
    if (isdigit(c)) {
      psz_field = psz_field * 10 + (c - '0');
      c = *psz_mmssff++;
    }
    else
      return CDIO_INVALID_LBA;
  }

  if('\0' != c)
    return CDIO_INVALID_LBA;

  if(psz_field >= CDIO_CD_FRAMES_PER_SEC)
    return CDIO_INVALID_LBA;

  ret += psz_field;

  return ret;
}
コード例 #3
0
ファイル: win32_ioctl.c プロジェクト: Crome/libcdio
/*!  
  Read and cache the CD's Track Table of Contents and track info.
  via a SCSI MMC READ_TOC (FULTOC).  Return true if successful or
  false if an error.
*/
static bool
read_fulltoc_win32mmc (_img_private_t *p_env) 
{
  mmc_cdb_t  cdb = {{0, }};
  CDROM_TOC_FULL  cdrom_toc_full;
  int             i_status, i, j;
  int             i_track_format = 0;
  int             i_seen_flag;

  /* Operation code */
  CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC);

  cdb.field[1] = 0x00;

  /* Format */
  cdb.field[2] = CDIO_MMC_READTOC_FMT_FULTOC;

  memset(&cdrom_toc_full, 0, sizeof(cdrom_toc_full));

  /* Setup to read header, to get length of data */
  CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(cdrom_toc_full));

  i_status = run_mmc_cmd_win32ioctl (p_env, 1000*60*3,
				     mmc_get_cmd_len(cdb.field[0]), 
				     &cdb, SCSI_MMC_DATA_READ, 
				     sizeof(cdrom_toc_full), &cdrom_toc_full);

  if ( 0 != i_status ) {
    cdio_debug ("SCSI MMC READ_TOC failed\n");  
    return false;
  } 
    
  i_seen_flag=0;
  for( i = 0 ; i <= CDIO_CD_MAX_TRACKS+3; i++ ) {
    
    if ( 0xA0 == cdrom_toc_full.TrackData[i].POINT ) { 
      /* First track number */
      p_env->gen.i_first_track = cdrom_toc_full.TrackData[i].PMIN;
      i_track_format = cdrom_toc_full.TrackData[i].PSEC;
      i_seen_flag|=0x01;
    }
    
    if ( 0xA1 == cdrom_toc_full.TrackData[i].POINT ) { 
      /* Last track number */
      p_env->gen.i_tracks = 
	cdrom_toc_full.TrackData[i].PMIN - p_env->gen.i_first_track + 1;
      i_seen_flag|=0x02;
    }

    j = cdrom_toc_full.TrackData[i].POINT;
    if ( 0xA2 ==  j ) { 
      /* Start position of the lead out */
      p_env->tocent[ p_env->gen.i_tracks ].start_lsn = 
	cdio_lba_to_lsn(
			cdio_msf3_to_lba(
					 cdrom_toc_full.TrackData[i].PMIN,
					 cdrom_toc_full.TrackData[i].PSEC,
					 cdrom_toc_full.TrackData[i].PFRAME 
					 )
			);
      p_env->tocent[ p_env->gen.i_tracks ].Control 
	= cdrom_toc_full.TrackData[i].Control;
      p_env->tocent[ p_env->gen.i_tracks ].Format  = i_track_format;
      i_seen_flag|=0x04;
    }
    
    if (cdrom_toc_full.TrackData[i].POINT > 0 
	&& cdrom_toc_full.TrackData[i].POINT <= p_env->gen.i_tracks) {
      p_env->tocent[j-1].start_lsn = 
	cdio_lba_to_lsn(
			cdio_msf3_to_lba(
					 cdrom_toc_full.TrackData[i].PMIN,
					 cdrom_toc_full.TrackData[i].PSEC,
					 cdrom_toc_full.TrackData[i].PFRAME 
					 )
			);
      p_env->tocent[j-1].Control = 
	cdrom_toc_full.TrackData[i].Control;
      p_env->tocent[j-1].Format  = i_track_format;
      
      set_track_flags(&(p_env->gen.track_flags[j]), 
		      p_env->tocent[j-1].Control);
    
      cdio_debug("p_sectors: %i, %lu", i, 
		 (unsigned long int) (p_env->tocent[i].start_lsn));
      
      if (cdrom_toc_full.TrackData[i].POINT == p_env->gen.i_tracks)
	i_seen_flag|=0x08;
    }
    
    if ( 0x0F == i_seen_flag ) break;
  }
  if ( 0x0F == i_seen_flag ) {
    p_env->gen.toc_init = true; 
    return true;
  }
  return false;
}