1 /*
2   Copyright (C) 2005, 2008 Rocky Bernstein <rocky@gnu.org>
3   Copyright (C) 2014 Robert Kausch <robert.kausch@freac.org>
4   Copyright (C) 1998 Monty xiphmont@mit.edu
5 
6   This program is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10 
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 /******************************************************************
20  * Top-level interface module for cdrom drive access.  SCSI, ATAPI, etc
21  *    specific stuff are in other modules.  Note that SCSI does use
22  *    specialized ioctls; these appear in common_interface.c where the
23  *    generic_scsi stuff is in scsi_interface.c.
24  *
25  ******************************************************************/
26 
27 #include "common_interface.h"
28 #include "low_interface.h"
29 #include "utils.h"
30 #include <cdio/bytesex.h>
31 #include <cdio/mmc.h>
32 #include <cdio/paranoia/version.h>
33 
cdio_cddap_version(void)34 extern const char *cdio_cddap_version(void){
35   return LIBCDIO_PARANOIA_VERSION;
36 }
37 
_clean_messages(cdrom_drive_t * d)38 static void _clean_messages(cdrom_drive_t *d)
39 {
40   if(d){
41     if(d->messagebuf)free(d->messagebuf);
42     if(d->errorbuf)free(d->errorbuf);
43     d->messagebuf=NULL;
44     d->errorbuf=NULL;
45   }
46 }
47 
48 /*!
49   Closes d and releases all storage associated with it except
50   the internal p_cdio pointer.
51 
52   @param d cdrom_drive_t object to be closed.
53   @return 0 if passed a null pointer and 1 if not in which case
54   some work was probably done.
55 
56   @see cdio_cddap_close
57 */
58 bool
cdio_cddap_close_no_free_cdio(cdrom_drive_t * d)59 cdio_cddap_close_no_free_cdio(cdrom_drive_t *d)
60 {
61   if(d){
62     if(d->opened)
63       d->enable_cdda(d,0);
64 
65     _clean_messages(d);
66     if (d->cdda_device_name) free(d->cdda_device_name);
67     if (d->drive_model)      free(d->drive_model);
68     d->cdda_device_name = d->drive_model = NULL;
69     free(d);
70     return true;
71   }
72   return false;
73 }
74 
75 /*!
76   Closes d and releases all storage associated with it.
77   Doubles as "cdrom_drive_free()".
78 
79   @param d cdrom_drive_t object to be closed.
80   @return 0 if passed a null pointer and 1 if not in which case
81   some work was probably done.
82 
83   @see cdio_cddap_close_no_free_cdio
84 */
85 int
cdio_cddap_close(cdrom_drive_t * d)86 cdio_cddap_close(cdrom_drive_t *d)
87 {
88   if (d) {
89     CdIo_t *p_cdio = d->p_cdio;
90     cdio_cddap_close_no_free_cdio(d);
91     cdio_destroy (p_cdio);
92     return 1;
93   }
94   return 0;
95 }
96 
97 /* finish initializing the drive! */
98 int
cdio_cddap_open(cdrom_drive_t * d)99 cdio_cddap_open(cdrom_drive_t *d)
100 {
101   int ret;
102   if(d->opened)return(0);
103 
104   if ( (ret=cddap_init_drive(d)) )
105     return(ret);
106 
107   /* Check TOC, enable for CDDA */
108 
109   /* Some drives happily return a TOC even if there is no disc... */
110   {
111     int i;
112     for(i=0; i<d->tracks; i++)
113       if(d->disc_toc[i].dwStartSector<0 ||
114 	 d->disc_toc[i+1].dwStartSector==0){
115 	d->opened=0;
116 	cderror(d,"009: CDROM reporting illegal table of contents\n");
117 	return(-9);
118       }
119   }
120 
121   if((ret=d->enable_cdda(d,1)))
122     return(ret);
123 
124   /*  d->select_speed(d,d->maxspeed); most drives are full speed by default */
125 
126   if ( -1 == d->bigendianp ) {
127     d->bigendianp = data_bigendianp(d);
128   }
129 
130 
131   return(0);
132 }
133 
134 int
cdio_cddap_speed_set(cdrom_drive_t * d,int speed)135 cdio_cddap_speed_set(cdrom_drive_t *d, int speed)
136 {
137   if(d->set_speed)
138     if(!d->set_speed(d, speed))return 0;
139 
140   cderror(d,"405: Option not supported by drive\n");
141   return -405;
142 }
143 
144 long
cdio_cddap_read_timed(cdrom_drive_t * d,void * buffer,lsn_t beginsector,long sectors,int * ms)145 cdio_cddap_read_timed(cdrom_drive_t *d, void *buffer, lsn_t beginsector,
146 		long sectors, int *ms)
147 {
148   if(ms)*ms= -1;
149   if (d->opened) {
150     if (sectors>0) {
151       sectors=d->read_audio(d, buffer, beginsector, sectors);
152 
153       if (sectors > 0) {
154 	/* byteswap? */
155 	if ( d->bigendianp == -1 ) /* not determined yet */
156 	  d->bigendianp = data_bigendianp(d);
157 
158 	if ( buffer && d->b_swap_bytes && d->bigendianp != bigendianp() ) {
159 	  int i;
160 	  uint16_t *p=(uint16_t *)buffer;
161 	  long els=sectors*CDIO_CD_FRAMESIZE_RAW/2;
162 
163 	  for(i=0;i<els;i++)
164 	    p[i]=UINT16_SWAP_LE_BE_C(p[i]);
165 	}
166       }
167     }
168     if(ms)*ms=d->last_milliseconds;
169     return(sectors);
170   }
171 
172   cderror(d,"400: Device not open\n");
173   return(-400);
174 }
175 
cdio_cddap_read(cdrom_drive_t * d,void * buffer,lsn_t beginsector,long sectors)176 long cdio_cddap_read(cdrom_drive_t *d, void *buffer, lsn_t beginsector, long sectors){
177   return cdda_read_timed(d,buffer,beginsector,sectors,NULL);
178 }
179 
180 void
cdio_cddap_verbose_set(cdrom_drive_t * d,int err_action,int mes_action)181 cdio_cddap_verbose_set(cdrom_drive_t *d,int err_action, int mes_action)
182 {
183   d->messagedest=mes_action;
184   d->errordest=err_action;
185 }
186 
187 extern char *
cdio_cddap_messages(cdrom_drive_t * d)188 cdio_cddap_messages(cdrom_drive_t *d)
189 {
190   char *ret=d->messagebuf;
191   d->messagebuf=NULL;
192   return(ret);
193 }
194 
195 extern char *
cdio_cddap_errors(cdrom_drive_t * d)196 cdio_cddap_errors(cdrom_drive_t *d)
197 {
198   char *ret=d->errorbuf;
199   d->errorbuf=NULL;
200   return(ret);
201 }
202 
203 extern void
cdio_cddap_free_messages(char * psz_messages)204 cdio_cddap_free_messages(char *psz_messages)
205 {
206   if (psz_messages != NULL)
207     free(psz_messages);
208 }
209