2005-01-06 03:38:58 +00:00
|
|
|
/*
|
2005-02-07 03:36:01 +00:00
|
|
|
$Id: interface.c,v 1.21 2005/02/07 03:36:02 rocky Exp $
|
2005-01-06 03:38:58 +00:00
|
|
|
|
|
|
|
|
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com>
|
|
|
|
|
Copyright (C) 1998 Monty xiphmont@mit.edu
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
*/
|
2004-12-18 17:29:32 +00:00
|
|
|
/******************************************************************
|
|
|
|
|
* Top-level interface module for cdrom drive access. SCSI, ATAPI, etc
|
|
|
|
|
* specific stuff are in other modules. Note that SCSI does use
|
|
|
|
|
* specialized ioctls; these appear in common_interface.c where the
|
|
|
|
|
* generic_scsi stuff is in scsi_interface.c.
|
|
|
|
|
*
|
|
|
|
|
******************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "common_interface.h"
|
2005-01-06 03:38:58 +00:00
|
|
|
#include "low_interface.h"
|
2004-12-18 17:29:32 +00:00
|
|
|
#include "utils.h"
|
2004-12-19 01:43:38 +00:00
|
|
|
#include <cdio/bytesex.h>
|
2005-02-07 03:36:01 +00:00
|
|
|
#include <cdio/mmc.h>
|
2004-12-18 17:29:32 +00:00
|
|
|
|
|
|
|
|
static void _clean_messages(cdrom_drive_t *d)
|
|
|
|
|
{
|
|
|
|
|
if(d){
|
|
|
|
|
if(d->messagebuf)free(d->messagebuf);
|
|
|
|
|
if(d->errorbuf)free(d->errorbuf);
|
|
|
|
|
d->messagebuf=NULL;
|
|
|
|
|
d->errorbuf=NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-26 01:03:16 +00:00
|
|
|
/*!
|
|
|
|
|
Closes d and releases all storage associated with it except
|
|
|
|
|
the internal p_cdio pointer.
|
|
|
|
|
|
|
|
|
|
@param d cdrom_drive_t object to be closed.
|
|
|
|
|
@return 0 if passed a null pointer and 1 if not in which case
|
|
|
|
|
some work was probably done.
|
|
|
|
|
|
|
|
|
|
@see cdio_cddap_close
|
|
|
|
|
*/
|
|
|
|
|
bool
|
|
|
|
|
cdio_cddap_close_no_free_cdio(cdrom_drive_t *d)
|
2004-12-18 17:29:32 +00:00
|
|
|
{
|
|
|
|
|
if(d){
|
|
|
|
|
if(d->opened)
|
|
|
|
|
d->enable_cdda(d,0);
|
|
|
|
|
|
|
|
|
|
_clean_messages(d);
|
2005-01-05 04:16:11 +00:00
|
|
|
if (d->cdda_device_name) free(d->cdda_device_name);
|
|
|
|
|
if (d->drive_model) free(d->drive_model);
|
2005-01-26 01:03:16 +00:00
|
|
|
d->cdda_device_name = d->drive_model = NULL;
|
2004-12-18 17:29:32 +00:00
|
|
|
free(d);
|
2005-01-26 01:03:16 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Closes d and releases all storage associated with it.
|
|
|
|
|
Doubles as "cdrom_drive_free()".
|
|
|
|
|
|
|
|
|
|
@param d cdrom_drive_t object to be closed.
|
|
|
|
|
@return 0 if passed a null pointer and 1 if not in which case
|
|
|
|
|
some work was probably done.
|
|
|
|
|
|
|
|
|
|
@see cdio_cddap_close_no_free_cdio
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
cdio_cddap_close(cdrom_drive_t *d)
|
|
|
|
|
{
|
|
|
|
|
if (d) {
|
|
|
|
|
CdIo_t *p_cdio = d->p_cdio;
|
|
|
|
|
cdio_cddap_close_no_free_cdio(d);
|
|
|
|
|
cdio_destroy (p_cdio);
|
|
|
|
|
return 1;
|
2004-12-18 17:29:32 +00:00
|
|
|
}
|
2005-01-26 01:03:16 +00:00
|
|
|
return 0;
|
2004-12-18 17:29:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* finish initializing the drive! */
|
|
|
|
|
int
|
2005-01-25 11:04:45 +00:00
|
|
|
cdio_cddap_open(cdrom_drive_t *d)
|
2004-12-18 17:29:32 +00:00
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
if(d->opened)return(0);
|
|
|
|
|
|
2005-02-05 16:25:51 +00:00
|
|
|
if ( (ret=cddap_init_drive(d)) )
|
2005-01-05 04:16:11 +00:00
|
|
|
return(ret);
|
2004-12-18 17:29:32 +00:00
|
|
|
|
|
|
|
|
/* Check TOC, enable for CDDA */
|
|
|
|
|
|
|
|
|
|
/* Some drives happily return a TOC even if there is no disc... */
|
|
|
|
|
{
|
|
|
|
|
int i;
|
2004-12-19 01:43:38 +00:00
|
|
|
for(i=0; i<d->tracks; i++)
|
2004-12-18 17:29:32 +00:00
|
|
|
if(d->disc_toc[i].dwStartSector<0 ||
|
|
|
|
|
d->disc_toc[i+1].dwStartSector==0){
|
|
|
|
|
d->opened=0;
|
|
|
|
|
cderror(d,"009: CDROM reporting illegal table of contents\n");
|
|
|
|
|
return(-9);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if((ret=d->enable_cdda(d,1)))
|
|
|
|
|
return(ret);
|
|
|
|
|
|
|
|
|
|
/* d->select_speed(d,d->maxspeed); most drives are full speed by default */
|
2005-02-07 03:36:01 +00:00
|
|
|
|
|
|
|
|
if ( -1 == d->bigendianp ) {
|
|
|
|
|
if (mmc_have_interface(d->p_cdio, CDIO_MMC_FEATURE_INTERFACE_ATAPI))
|
|
|
|
|
/* Is this right? */
|
|
|
|
|
d->bigendianp = 1;
|
|
|
|
|
else
|
|
|
|
|
d->bigendianp = data_bigendianp(d);
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-14 03:41:11 +00:00
|
|
|
|
2004-12-18 17:29:32 +00:00
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2005-01-25 11:04:45 +00:00
|
|
|
cdio_cddap_speed_set(cdrom_drive_t *d, int speed)
|
2004-12-18 17:29:32 +00:00
|
|
|
{
|
|
|
|
|
return d->set_speed ? d->set_speed(d, speed) : 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-25 11:04:45 +00:00
|
|
|
long
|
|
|
|
|
cdio_cddap_read(cdrom_drive_t *d, void *buffer, lsn_t beginsector,
|
|
|
|
|
long sectors)
|
2004-12-18 17:29:32 +00:00
|
|
|
{
|
2005-01-23 14:05:19 +00:00
|
|
|
if (d->opened) {
|
|
|
|
|
if (sectors>0) {
|
|
|
|
|
sectors=d->read_audio(d, buffer, beginsector, sectors);
|
2004-12-18 17:29:32 +00:00
|
|
|
|
2005-01-27 03:10:06 +00:00
|
|
|
if (sectors > 0) {
|
2004-12-18 17:29:32 +00:00
|
|
|
/* byteswap? */
|
2005-01-27 03:10:06 +00:00
|
|
|
if ( d->bigendianp == -1 ) /* not determined yet */
|
2005-01-23 14:05:19 +00:00
|
|
|
d->bigendianp = data_bigendianp(d);
|
|
|
|
|
|
2005-01-27 03:10:06 +00:00
|
|
|
if ( d->b_swap_bytes && d->bigendianp != bigendianp() ) {
|
2004-12-18 17:29:32 +00:00
|
|
|
int i;
|
2005-01-06 03:09:11 +00:00
|
|
|
uint16_t *p=(uint16_t *)buffer;
|
|
|
|
|
long els=sectors*CDIO_CD_FRAMESIZE_RAW/2;
|
2004-12-18 17:29:32 +00:00
|
|
|
|
2005-01-27 03:10:06 +00:00
|
|
|
/* Note: Something perhaps in the original cdparanoia code might
|
2005-01-23 14:05:19 +00:00
|
|
|
cause the code to access outside of the allocated range of
|
|
|
|
|
buffer. This comment is just to serve as a marker for
|
|
|
|
|
the loop where the data got clobbered. I don't think this
|
|
|
|
|
code however is wrong. See the comment in i_read_c_block
|
|
|
|
|
of paranioa.c
|
|
|
|
|
*/
|
2004-12-19 01:43:38 +00:00
|
|
|
for(i=0;i<els;i++)
|
|
|
|
|
p[i]=UINT16_SWAP_LE_BE_C(p[i]);
|
2004-12-18 17:29:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return(sectors);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cderror(d,"400: Device not open\n");
|
|
|
|
|
return(-400);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2005-01-25 11:04:45 +00:00
|
|
|
cdio_cddap_verbose_set(cdrom_drive_t *d,int err_action, int mes_action)
|
2004-12-18 17:29:32 +00:00
|
|
|
{
|
|
|
|
|
d->messagedest=mes_action;
|
|
|
|
|
d->errordest=err_action;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-25 11:04:45 +00:00
|
|
|
extern char *
|
|
|
|
|
cdio_cddap_messages(cdrom_drive_t *d)
|
2004-12-18 17:29:32 +00:00
|
|
|
{
|
|
|
|
|
char *ret=d->messagebuf;
|
|
|
|
|
d->messagebuf=NULL;
|
|
|
|
|
return(ret);
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-25 11:04:45 +00:00
|
|
|
extern char *
|
|
|
|
|
cdio_cddap_errors(cdrom_drive_t *d)
|
2004-12-18 17:29:32 +00:00
|
|
|
{
|
|
|
|
|
char *ret=d->errorbuf;
|
|
|
|
|
d->errorbuf=NULL;
|
|
|
|
|
return(ret);
|
|
|
|
|
}
|
|
|
|
|
|