2
$Id: scan_devices.c,v 1.29 2005/08/27 14:28:30 rocky Exp $
4
Copyright (C) 2004, 2005 Rocky Bernstein <rocky@panix.com>
5
Copyright (C) 1998 Monty xiphmont@mit.edu
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
/******************************************************************
24
* Autoscan for or verify presence of a CD-ROM device
26
******************************************************************/
28
#include "common_interface.h"
29
#include "low_interface.h"
39
#ifdef HAVE_SYS_STAT_H
43
#define MAX_DEV_LEN 20 /* Safe because strings only come from below */
44
/* must be absolute paths! */
45
const char *scsi_cdrom_prefixes[]={
49
const char *scsi_generic_prefixes[]={
53
const char *devfs_scsi_test="/dev/scsi/";
54
const char *devfs_scsi_cd="cd";
55
const char *devfs_scsi_generic="generic";
57
const char *cdrom_devices[]={
69
/* "/dev/aztcd", timeout is too long */
74
static cdrom_drive_t *
75
cdda_identify_device_cdio(CdIo_t *p_cdio, const char *psz_device,
76
int messagedest, char **ppsz_messages);
78
/* Functions here look for a cdrom drive; full init of a drive type
79
happens in interface.c */
82
cdio_cddap_find_a_cdrom(int messagedest, char **ppsz_messages){
88
while(cdrom_devices[i]!=NULL){
90
/* is it a name or a pattern? */
92
if((pos=strchr(cdrom_devices[i],'?'))){
94
/* try first eight of each device */
96
char *buffer=strdup(cdrom_devices[i]);
98
/* number, then letter */
100
buffer[pos-(cdrom_devices[i])]=j+48;
101
if((d=cdda_identify(buffer, messagedest, ppsz_messages)))
103
idmessage(messagedest, ppsz_messages, "", NULL);
104
buffer[pos-(cdrom_devices[i])]=j+97;
105
if((d=cdda_identify(buffer, messagedest, ppsz_messages)))
107
idmessage(messagedest, ppsz_messages, "", NULL);
110
/* Name. Go for it. */
111
if((d=cdda_identify(cdrom_devices[i], messagedest, ppsz_messages)))
114
idmessage(messagedest, ppsz_messages, "", NULL);
119
#if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
121
temp=getpwuid(geteuid());
122
idmessage(messagedest, ppsz_messages,
123
"\n\nNo cdrom drives accessible to %s found.\n",
126
idmessage(messagedest, ppsz_messages,
127
"\n\nNo cdrom drives accessible found.\n", NULL);
133
#ifdef DEVICE_IN_FILESYSTEM
135
test_resolve_symlink(const char *file, int messagedest, char **ppsz_messages)
137
char resolved[PATH_MAX];
139
if (lstat(file,&st)){
140
idperror(messagedest, ppsz_messages, "\t\tCould not stat %s",file);
144
if (realpath(file,resolved))
145
return(strdup(resolved));
147
idperror(messagedest, ppsz_messages, "\t\tCould not resolve symlink %s",
153
/** Returns a paranoia CD-ROM drive object with a CD-DA in it or NULL
154
if there was an error.
155
@see cdio_cddap_identify_cdio
158
cdio_cddap_identify(const char *psz_dev, int messagedest,
159
char **ppsz_messages)
161
CdIo_t *p_cdio = NULL;
164
idmessage(messagedest, ppsz_messages, "Checking %s for cdrom...",
167
idmessage(messagedest, ppsz_messages, "Checking for cdrom...", NULL);
169
#ifdef DEVICE_IN_FILESYSTEM
171
char *psz_device = test_resolve_symlink(psz_dev, messagedest,
174
cdrom_drive_t *d=NULL;
175
p_cdio = cdio_open(psz_device, DRIVER_UNKNOWN);
176
d = cdda_identify_device_cdio(p_cdio, psz_device, messagedest,
184
p_cdio = cdio_open(psz_dev, DRIVER_UNKNOWN);
187
psz_dev = cdio_get_arg(p_cdio, "source");
189
return cdda_identify_device_cdio(p_cdio, psz_dev, messagedest,
195
/** Returns a paranoia CD-ROM drive object with a CD-DA in it or NULL
196
if there was an error. In contrast to cdio_cddap_identify, we
197
start out with an initialized p_cdio object. For example you may
198
have used that for other purposes such as to get CDDB/CD-Text
199
information. @see cdio_cddap_identify
202
cdio_cddap_identify_cdio(CdIo_t *p_cdio, int messagedest, char **ppsz_messages)
204
if (!p_cdio) return NULL;
206
const char *psz_device = cdio_get_arg(p_cdio, "source");
207
idmessage(messagedest, ppsz_messages, "Checking %s for cdrom...",
209
return cdda_identify_device_cdio(p_cdio, psz_device, messagedest,
215
static cdrom_drive_t *
216
cdda_identify_device_cdio(CdIo_t *p_cdio, const char *psz_device,
217
int messagedest, char **ppsz_messages)
219
cdrom_drive_t *d=NULL;
221
char *description=NULL;
222
#ifdef HAVE_LINUX_MAJOR_H
227
idperror(messagedest, ppsz_messages, "\t\tUnable to open %s", psz_device);
231
#ifdef HAVE_LINUX_MAJOR_H
232
if ( 0 == stat(psz_device, &st) ) {
233
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
234
drive_type=(int)(st.st_rdev>>8);
235
switch (drive_type) {
241
description=strdup("ATAPI compatible ");
243
case CDU31A_CDROM_MAJOR:
244
/* major indicates this is a cdrom; no ping necessary. */
245
description=strdup("Sony CDU31A or compatible");
247
case CDU535_CDROM_MAJOR:
248
/* major indicates this is a cdrom; no ping necessary. */
249
description=strdup("Sony CDU535 or compatible");
252
case MATSUSHITA_CDROM_MAJOR:
253
case MATSUSHITA_CDROM2_MAJOR:
254
case MATSUSHITA_CDROM3_MAJOR:
255
case MATSUSHITA_CDROM4_MAJOR:
256
/* major indicates this is a cdrom; no ping necessary. */
257
description=strdup("non-ATAPI IDE-style Matsushita/Panasonic CR-5xx or compatible");
259
case SANYO_CDROM_MAJOR:
260
description=strdup("Sanyo proprietary or compatible: NOT CDDA CAPABLE");
262
case MITSUMI_CDROM_MAJOR:
263
case MITSUMI_X_CDROM_MAJOR:
264
description=strdup("Mitsumi proprietary or compatible: NOT CDDA CAPABLE");
266
case OPTICS_CDROM_MAJOR:
267
description=strdup("Optics Dolphin or compatible: NOT CDDA CAPABLE");
269
case AZTECH_CDROM_MAJOR:
270
description=strdup("Aztech proprietary or compatible: NOT CDDA CAPABLE");
272
case GOLDSTAR_CDROM_MAJOR:
273
description=strdup("Goldstar proprietary: NOT CDDA CAPABLE");
275
case CM206_CDROM_MAJOR:
276
description=strdup("Philips/LMS CM206 proprietary: NOT CDDA CAPABLE");
279
case SCSI_CDROM_MAJOR:
280
case SCSI_GENERIC_MAJOR:
282
description=strdup("SCSI CD-ROM");
285
/* What the hell is this? */
286
idmessage(messagedest, ppsz_messages,
287
"\t\t%s is not a cooked ioctl CDROM.",
293
#endif /*HAVE_LINUX_MAJOR_H*/
297
d=calloc(1,sizeof(cdrom_drive_t));
299
d->cdda_device_name = strdup(psz_device);
300
d->drive_type = drive_type;
301
d->bigendianp = -1; /* We don't know yet... */
302
d->nsectors = -1; /* We don't know yet... */
303
d->b_swap_bytes = true;
306
cdio_hwinfo_t hw_info;
308
if ( mmc_get_hwinfo( p_cdio, &hw_info ) ) {
309
unsigned int i_len = strlen(hw_info.psz_vendor)
310
+ strlen(hw_info.psz_model)
311
+ strlen(hw_info.psz_revision) + 5;
314
i_len += strlen(description);
315
d->drive_model=malloc( i_len );
316
snprintf( d->drive_model, i_len, "%s %s %s %s",
317
hw_info.psz_vendor, hw_info.psz_model, hw_info.psz_revision,
321
d->drive_model=malloc( i_len );
322
snprintf( d->drive_model, i_len, "%s %s %s",
323
hw_info.psz_vendor, hw_info.psz_model, hw_info.psz_revision
326
idmessage(messagedest, ppsz_messages, "\t\tCDROM sensed: %s\n",