Blame lib/driver/sector.c

Packit dd8086
/*
Packit dd8086
  Copyright (C) 2004, 2005, 2011, 2012, 2014, 2016
Packit dd8086
  Rocky Bernstein <rocky@gnu.org>
Packit dd8086
  Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
Packit dd8086
Packit dd8086
  This program is free software: you can redistribute it and/or modify
Packit dd8086
  it under the terms of the GNU General Public License as published by
Packit dd8086
  the Free Software Foundation, either version 3 of the License, or
Packit dd8086
  (at your option) any later version.
Packit dd8086
Packit dd8086
  This program is distributed in the hope that it will be useful,
Packit dd8086
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit dd8086
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit dd8086
  GNU General Public License for more details.
Packit dd8086
Packit dd8086
  You should have received a copy of the GNU General Public License
Packit dd8086
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit dd8086
*/
Packit dd8086

Packit dd8086
#ifdef HAVE_CONFIG_H
Packit dd8086
# include "config.h"
Packit dd8086
# define __CDIO_CONFIG_H__ 1
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#include <cdio/sector.h>
Packit dd8086
#include <cdio/util.h>
Packit dd8086
#include <cdio/logging.h>
Packit dd8086
#include "cdio_assert.h"
Packit dd8086
#include "portable.h"
Packit dd8086
Packit dd8086
#ifdef HAVE_STDIO_H
Packit dd8086
#include <stdio.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_STRING_H
Packit dd8086
#include <string.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#include <ctype.h>
Packit dd8086
Packit dd8086
/*! String of bytes used to identify the beginning of a Mode 1 or
Packit dd8086
  Mode 2 sector. */
Packit dd8086
const uint8_t CDIO_SECTOR_SYNC_HEADER[CDIO_CD_SYNC_SIZE] =
Packit dd8086
  {0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0};
Packit dd8086
Packit dd8086
/* Variables to hold debugger-helping enumerations */
Packit dd8086
enum cdio_cd_enums;
Packit dd8086
enum m2_sector_enums;
Packit dd8086
Packit dd8086
lba_t
Packit dd8086
cdio_lba_to_lsn (lba_t lba)
Packit dd8086
{
Packit dd8086
  if (CDIO_INVALID_LBA     == lba) return CDIO_INVALID_LSN;
Packit dd8086
  return lba - CDIO_PREGAP_SECTORS;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*
Packit dd8086
   The below is adapted from cdparanoia code which claims it is
Packit dd8086
   straight from the MMC3 spec.
Packit dd8086
*/
Packit dd8086
Packit dd8086
void
Packit dd8086
cdio_lsn_to_msf (lsn_t lsn, msf_t *msf)
Packit dd8086
{
Packit dd8086
  int m, s, f;
Packit dd8086
Packit dd8086
  cdio_assert (msf != 0);
Packit dd8086
Packit dd8086
  if ( lsn >= -CDIO_PREGAP_SECTORS ){
Packit dd8086
    m    = (lsn + CDIO_PREGAP_SECTORS) / CDIO_CD_FRAMES_PER_MIN;
Packit dd8086
    lsn -= m * CDIO_CD_FRAMES_PER_MIN;
Packit dd8086
    s    = (lsn + CDIO_PREGAP_SECTORS) / CDIO_CD_FRAMES_PER_SEC;
Packit dd8086
    lsn -= s * CDIO_CD_FRAMES_PER_SEC;
Packit dd8086
    f    = lsn + CDIO_PREGAP_SECTORS;
Packit dd8086
  } else {
Packit dd8086
    m    = (lsn + CDIO_CD_MAX_LSN)     / CDIO_CD_FRAMES_PER_MIN;
Packit dd8086
    lsn -= m * (CDIO_CD_FRAMES_PER_MIN);
Packit dd8086
    s    = (lsn+CDIO_CD_MAX_LSN)       / CDIO_CD_FRAMES_PER_SEC;
Packit dd8086
    lsn -= s * CDIO_CD_FRAMES_PER_SEC;
Packit dd8086
    f    = lsn + CDIO_CD_MAX_LSN;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (m > 99) {
Packit dd8086
    cdio_warn ("number of minutes (%d) truncated to 99.", m);
Packit dd8086
    m = 99;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  msf->m = cdio_to_bcd8 (m);
Packit dd8086
  msf->s = cdio_to_bcd8 (s);
Packit dd8086
  msf->f = cdio_to_bcd8 (f);
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Convert an LBA into a string representation of the MSF.
Packit dd8086
  \warning cdio_lba_to_msf_str returns new allocated string */
Packit dd8086
char *
Packit dd8086
cdio_lba_to_msf_str (lba_t lba)
Packit dd8086
{
Packit dd8086
Packit dd8086
  if (CDIO_INVALID_LBA == lba) {
Packit dd8086
    return strdup("*INVALID");
Packit dd8086
  } else {
Packit dd8086
    msf_t msf;
Packit dd8086
    msf.m = msf.s = msf.f = 0;
Packit dd8086
    cdio_lba_to_msf (lba, &msf;;
Packit dd8086
    return cdio_msf_to_str(&msf;;
Packit dd8086
  }
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Convert an LSN into the corresponding LBA.
Packit dd8086
  CDIO_INVALID_LBA is returned if there is an error.
Packit dd8086
*/
Packit dd8086
lba_t
Packit dd8086
cdio_lsn_to_lba (lsn_t lsn)
Packit dd8086
{
Packit dd8086
  if (CDIO_INVALID_LSN  == lsn) return CDIO_INVALID_LBA;
Packit dd8086
  return lsn + CDIO_PREGAP_SECTORS;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Convert an LBA into the corresponding MSF.
Packit dd8086
*/
Packit dd8086
void
Packit dd8086
cdio_lba_to_msf (lba_t lba, msf_t *msf)
Packit dd8086
{
Packit dd8086
  cdio_assert (msf != 0);
Packit dd8086
  cdio_lsn_to_msf(cdio_lba_to_lsn(lba), msf);
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Convert a MSF into the corresponding LBA.
Packit dd8086
  CDIO_INVALID_LBA is returned if there is an error.
Packit dd8086
*/
Packit dd8086
lba_t
Packit dd8086
cdio_msf_to_lba (const msf_t *msf)
Packit dd8086
{
Packit dd8086
  uint32_t lba = 0;
Packit dd8086
Packit dd8086
  cdio_assert (msf != 0);
Packit dd8086
Packit dd8086
  lba = cdio_from_bcd8 (msf->m);
Packit dd8086
  lba *= CDIO_CD_SECS_PER_MIN;
Packit dd8086
Packit dd8086
  lba += cdio_from_bcd8 (msf->s);
Packit dd8086
  lba *= CDIO_CD_FRAMES_PER_SEC;
Packit dd8086
Packit dd8086
  lba += cdio_from_bcd8 (msf->f);
Packit dd8086
Packit dd8086
  return lba;
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Convert a MSF into the corresponding LSN.
Packit dd8086
  CDIO_INVALID_LSN is returned if there is an error.
Packit dd8086
*/
Packit dd8086
lba_t
Packit dd8086
cdio_msf_to_lsn (const msf_t *msf)
Packit dd8086
{
Packit dd8086
  return cdio_lba_to_lsn(cdio_msf_to_lba (msf));
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Convert an LBA into a string representation of the MSF.
Packit dd8086
  \warning cdio_lba_to_msf_str returns new allocated string */
Packit dd8086
char *
Packit dd8086
cdio_msf_to_str (const msf_t *msf)
Packit dd8086
{
Packit dd8086
  char buf[16];
Packit dd8086
Packit dd8086
  snprintf (buf, sizeof (buf), "%2.2x:%2.2x:%2.2x", msf->m, msf->s, msf->f);
Packit dd8086
  return strdup (buf);
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Convert a MSF - broken out as 3 integer components into the
Packit dd8086
  corresponding LBA.
Packit dd8086
  CDIO_INVALID_LBA is returned if there is an error.
Packit dd8086
*/
Packit dd8086
lba_t
Packit dd8086
cdio_msf3_to_lba (unsigned int minutes, unsigned int seconds,
Packit dd8086
                  unsigned int frames)
Packit dd8086
{
Packit dd8086
  return ((minutes * CDIO_CD_SECS_PER_MIN + seconds) * CDIO_CD_FRAMES_PER_SEC
Packit dd8086
	  + frames);
Packit dd8086
}
Packit dd8086
Packit dd8086
/*!
Packit dd8086
  Convert a string of the form MM:SS:FF into the corresponding LBA.
Packit dd8086
  CDIO_INVALID_LBA is returned if there is an error.
Packit dd8086
*/
Packit dd8086
lba_t
Packit dd8086
cdio_mmssff_to_lba (const char *psz_mmssff)
Packit dd8086
{
Packit dd8086
  int psz_field;
Packit dd8086
  lba_t ret;
Packit dd8086
  unsigned char c;
Packit dd8086
Packit dd8086
  if (0 == strcmp (psz_mmssff, "0"))
Packit dd8086
    return 0;
Packit dd8086
Packit dd8086
  c = *psz_mmssff++;
Packit dd8086
  if(c >= '0' && c <= '9')
Packit dd8086
    psz_field = (c - '0');
Packit dd8086
  else
Packit dd8086
    return CDIO_INVALID_LBA;
Packit dd8086
  while(':' != (c = *psz_mmssff++)) {
Packit dd8086
    if(c >= '0' && c <= '9')
Packit dd8086
      psz_field = psz_field * 10 + (c - '0');
Packit dd8086
    else
Packit dd8086
      return CDIO_INVALID_LBA;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  ret = cdio_msf3_to_lba (psz_field, 0, 0);
Packit dd8086
Packit dd8086
  c = *psz_mmssff++;
Packit dd8086
  if(c >= '0' && c <= '9')
Packit dd8086
    psz_field = (c - '0');
Packit dd8086
  else
Packit dd8086
    return CDIO_INVALID_LBA;
Packit dd8086
  if(':' != (c = *psz_mmssff++)) {
Packit dd8086
    if(c >= '0' && c <= '9') {
Packit dd8086
      psz_field = psz_field * 10 + (c - '0');
Packit dd8086
      c = *psz_mmssff++;
Packit dd8086
      if(c != ':')
Packit dd8086
	return CDIO_INVALID_LBA;
Packit dd8086
    }
Packit dd8086
    else
Packit dd8086
      return CDIO_INVALID_LBA;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if(psz_field >= CDIO_CD_SECS_PER_MIN)
Packit dd8086
    return CDIO_INVALID_LBA;
Packit dd8086
Packit dd8086
  ret += cdio_msf3_to_lba (0, psz_field, 0);
Packit dd8086
Packit dd8086
  c = *psz_mmssff++;
Packit dd8086
  if (isdigit(c))
Packit dd8086
    psz_field = (c - '0');
Packit dd8086
  else
Packit dd8086
    return -1;
Packit dd8086
  if('\0' != (c = *psz_mmssff++)) {
Packit dd8086
    if (isdigit(c)) {
Packit dd8086
      psz_field = psz_field * 10 + (c - '0');
Packit dd8086
      c = *psz_mmssff++;
Packit dd8086
    }
Packit dd8086
    else
Packit dd8086
      return CDIO_INVALID_LBA;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if('\0' != c)
Packit dd8086
    return CDIO_INVALID_LBA;
Packit dd8086
Packit dd8086
  if(psz_field >= CDIO_CD_FRAMES_PER_SEC)
Packit dd8086
    return CDIO_INVALID_LBA;
Packit dd8086
Packit dd8086
  ret += psz_field;
Packit dd8086
Packit dd8086
  return ret;
Packit dd8086
}
Packit dd8086
Packit dd8086

Packit dd8086
/*
Packit dd8086
 * Local variables:
Packit dd8086
 *  c-file-style: "gnu"
Packit dd8086
 *  tab-width: 8
Packit dd8086
 *  indent-tabs-mode: nil
Packit dd8086
 * End:
Packit dd8086
 */