2
$Id: _cdio_linux.c,v 1.99 2004/11/20 12:41:21 rocky Exp $
4
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
5
Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com>
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
/* This file contains Linux-specific code and implements low-level
23
control of the CD drive.
30
static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.99 2004/11/20 12:41:21 rocky Exp $";
34
#include <cdio/sector.h>
35
#include <cdio/util.h>
36
#include <cdio/types.h>
37
#include <cdio/scsi_mmc.h>
38
#include <cdio/cdtext.h>
39
#include "cdtext_private.h"
40
#include "cdio_assert.h"
41
#include "cdio_private.h"
43
#ifdef HAVE_LINUX_CDROM
45
#if defined(HAVE_LINUX_VERSION_H)
46
# include <linux/version.h>
47
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16)
48
# define __CDIO_LINUXCD_BUILD
50
# error "You need a kernel greater than 2.2.16 to have CDROM support"
53
# error "You need <linux/version.h> to have CDROM support"
63
#include <linux/cdrom.h>
64
#include <scsi/scsi.h>
66
#include <scsi/scsi_ioctl.h>
67
#include <sys/mount.h>
70
#include <sys/types.h>
71
#include <sys/ioctl.h>
81
/* Things common to all drivers like this.
82
This must be first. */
83
generic_img_private_t gen;
85
access_mode_t access_mode;
87
/* Some of the more OS specific things. */
88
/* Entry info for each track, add 1 for leadout. */
89
struct cdrom_tocentry tocent[CDIO_CD_MAX_TRACKS+1];
91
struct cdrom_tochdr tochdr;
95
/* Some ioctl() errno values which occur when the tray is empty */
96
#define ERRNO_TRAYEMPTY(errno) \
97
((errno == EIO) || (errno == ENOENT) || (errno == EINVAL))
99
/**** prototypes for static functions ****/
100
static bool is_cdrom_linux(const char *drive, char *mnttype);
101
static bool read_toc_linux (void *p_user_data);
102
static int run_scsi_cmd_linux( const void *p_user_data,
103
unsigned int i_timeout,
105
const scsi_mmc_cdb_t *p_cdb,
106
scsi_mmc_direction_t e_direction,
108
/*in/out*/ void *p_buf );
111
str_to_access_mode_linux(const char *psz_access_mode)
113
const access_mode_t default_access_mode = _AM_IOCTL;
115
if (NULL==psz_access_mode) return default_access_mode;
117
if (!strcmp(psz_access_mode, "IOCTL"))
119
else if (!strcmp(psz_access_mode, "READ_CD"))
121
else if (!strcmp(psz_access_mode, "READ_10"))
124
cdio_warn ("unknown access type: %s. Default IOCTL used.",
126
return default_access_mode;
131
check_mounts_linux(const char *mtab)
134
struct mntent *mntent;
136
mntfp = setmntent(mtab, "r");
137
if ( mntfp != NULL ) {
142
while ( (mntent=getmntent(mntfp)) != NULL ) {
143
mnt_type = malloc(strlen(mntent->mnt_type) + 1);
144
if (mnt_type == NULL)
145
continue; /* maybe you'll get lucky next time. */
147
mnt_dev = malloc(strlen(mntent->mnt_fsname) + 1);
148
if (mnt_dev == NULL) {
153
strcpy(mnt_type, mntent->mnt_type);
154
strcpy(mnt_dev, mntent->mnt_fsname);
156
/* Handle "supermount" filesystem mounts */
157
if ( strcmp(mnt_type, "supermount") == 0 ) {
158
tmp = strstr(mntent->mnt_opts, "fs=");
161
mnt_type = strdup(tmp + strlen("fs="));
163
tmp = strchr(mnt_type, ',');
169
tmp = strstr(mntent->mnt_opts, "dev=");
172
mnt_dev = strdup(tmp + strlen("dev="));
174
tmp = strchr(mnt_dev, ',');
181
if ( strcmp(mnt_type, "iso9660") == 0 ) {
182
if (is_cdrom_linux(mnt_dev, mnt_type) > 0) {
197
Return the value associated with the key "arg".
200
get_arg_linux (void *env, const char key[])
202
_img_private_t *_obj = env;
204
if (!strcmp (key, "source")) {
205
return _obj->gen.source_name;
206
} else if (!strcmp (key, "access-mode")) {
207
switch (_obj->access_mode) {
215
return "no access method";
224
Return the the kind of drive capabilities of device.
226
Note: string is malloc'd so caller should free() then returned
227
string when done with it.
231
get_drive_cap_linux (const void *p_user_data,
232
/*out*/ cdio_drive_read_cap_t *p_read_cap,
233
/*out*/ cdio_drive_write_cap_t *p_write_cap,
234
/*out*/ cdio_drive_misc_cap_t *p_misc_cap)
236
const _img_private_t *p_env = p_user_data;
239
i_drivetype = ioctl (p_env->gen.fd, CDROM_GET_CAPABILITY, CDSL_CURRENT);
241
if (i_drivetype < 0) {
242
*p_read_cap = CDIO_DRIVE_CAP_ERROR;
243
*p_write_cap = CDIO_DRIVE_CAP_ERROR;
244
*p_misc_cap = CDIO_DRIVE_CAP_ERROR;
253
if (i_drivetype & CDC_PLAY_AUDIO)
254
*p_read_cap |= CDIO_DRIVE_CAP_READ_AUDIO;
255
if (i_drivetype & CDC_CD_R)
256
*p_read_cap |= CDIO_DRIVE_CAP_READ_CD_R;
257
if (i_drivetype & CDC_CD_RW)
258
*p_read_cap |= CDIO_DRIVE_CAP_READ_CD_RW;
259
if (i_drivetype & CDC_DVD)
260
*p_read_cap |= CDIO_DRIVE_CAP_READ_DVD_ROM;
263
if (i_drivetype & CDC_CD_RW)
264
*p_read_cap |= CDIO_DRIVE_CAP_WRITE_CD_RW;
265
if (i_drivetype & CDC_DVD_R)
266
*p_read_cap |= CDIO_DRIVE_CAP_WRITE_DVD_R;
267
if (i_drivetype & CDC_DVD_RAM)
268
*p_read_cap |= CDIO_DRIVE_CAP_WRITE_DVD_RAM;
271
if (i_drivetype & CDC_CLOSE_TRAY)
272
*p_misc_cap |= CDIO_DRIVE_CAP_MISC_CLOSE_TRAY;
273
if (i_drivetype & CDC_OPEN_TRAY)
274
*p_misc_cap |= CDIO_DRIVE_CAP_MISC_EJECT;
275
if (i_drivetype & CDC_LOCK)
276
*p_misc_cap |= CDIO_DRIVE_CAP_MISC_LOCK;
277
if (i_drivetype & CDC_SELECT_SPEED)
278
*p_misc_cap |= CDIO_DRIVE_CAP_MISC_SELECT_SPEED;
279
if (i_drivetype & CDC_SELECT_DISC)
280
*p_misc_cap |= CDIO_DRIVE_CAP_MISC_SELECT_DISC;
281
if (i_drivetype & CDC_MULTI_SESSION)
282
*p_misc_cap |= CDIO_DRIVE_CAP_MISC_MULTI_SESSION;
283
if (i_drivetype & CDC_MEDIA_CHANGED)
284
*p_misc_cap |= CDIO_DRIVE_CAP_MISC_MEDIA_CHANGED;
285
if (i_drivetype & CDC_RESET)
286
*p_misc_cap |= CDIO_DRIVE_CAP_MISC_RESET;
291
Return the media catalog number MCN.
293
Note: string is malloc'd so caller should free() then returned
294
string when done with it.
298
get_mcn_linux (const void *p_user_data) {
300
struct cdrom_mcn mcn;
301
const _img_private_t *p_env = p_user_data;
302
memset(&mcn, 0, sizeof(mcn));
303
if (ioctl(p_env->gen.fd, CDROM_GET_MCN, &mcn) != 0)
305
return strdup(mcn.medium_catalog_number);
311
static track_format_t
312
get_track_format_linux(void *p_user_data, track_t i_track)
314
_img_private_t *p_env = p_user_data;
316
if ( !p_env ) return TRACK_FORMAT_ERROR;
318
if (!p_env->gen.toc_init) read_toc_linux (p_user_data) ;
320
if (i_track > (p_env->gen.i_tracks+p_env->gen.i_first_track)
321
|| i_track < p_env->gen.i_first_track)
322
return TRACK_FORMAT_ERROR;
324
i_track -= p_env->gen.i_first_track;
326
/* This is pretty much copied from the "badly broken" cdrom_count_tracks
329
if (p_env->tocent[i_track].cdte_ctrl & CDIO_CDROM_DATA_TRACK) {
330
if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_CDI_TRACK)
331
return TRACK_FORMAT_CDI;
332
else if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_XA_TRACK)
333
return TRACK_FORMAT_XA;
335
return TRACK_FORMAT_DATA;
337
return TRACK_FORMAT_AUDIO;
342
Return true if we have XA data (green, mode2 form1) or
343
XA data (green, mode2 form2). That is track begins:
344
sync - header - subheader
347
FIXME: there's gotta be a better design for this and get_track_format?
350
get_track_green_linux(void *p_user_data, track_t i_track)
352
_img_private_t *p_env = p_user_data;
354
if (!p_env->gen.toc_init) read_toc_linux (p_user_data) ;
356
if (i_track >= (p_env->gen.i_tracks+p_env->gen.i_first_track)
357
|| i_track < p_env->gen.i_first_track)
360
i_track -= p_env->gen.i_first_track;
362
/* FIXME: Dunno if this is the right way, but it's what
363
I was using in cd-info for a while.
365
return ((p_env->tocent[i_track].cdte_ctrl & 2) != 0);
369
Return the starting MSF (minutes/secs/frames) for track number
370
track_num in obj. Track numbers usually start at something
371
greater than 0, usually 1.
373
The "leadout" track is specified either by
374
using i_track LEADOUT_TRACK or the total tracks+1.
375
False is returned if there is no track entry.
378
get_track_msf_linux(void *p_user_data, track_t i_track, msf_t *msf)
380
_img_private_t *p_env = p_user_data;
382
if (NULL == msf) return false;
384
if (!p_env->gen.toc_init) read_toc_linux (p_user_data) ;
386
if (i_track == CDIO_CDROM_LEADOUT_TRACK)
387
i_track = p_env->gen.i_tracks + p_env->gen.i_first_track;
389
if (i_track > (p_env->gen.i_tracks+p_env->gen.i_first_track)
390
|| i_track < p_env->gen.i_first_track) {
393
struct cdrom_msf0 *msf0=
394
&p_env->tocent[i_track-p_env->gen.i_first_track].cdte_addr.msf;
395
msf->m = cdio_to_bcd8(msf0->minute);
396
msf->s = cdio_to_bcd8(msf0->second);
397
msf->f = cdio_to_bcd8(msf0->frame);
403
Eject media in CD drive.
404
Return 0 if success and 1 for failure, and 2 if no routine.
407
eject_media_linux (void *p_user_data) {
409
_img_private_t *p_env = p_user_data;
414
if ((fd = open (p_env->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) {
415
if((status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) > 0) {
418
if((ret = ioctl(fd, CDROMCLOSETRAY)) != 0) {
419
cdio_warn ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno));
424
if((ret = ioctl(fd, CDROMEJECT)) != 0) {
425
int eject_error = errno;
426
/* Try ejecting the MMC way... */
427
ret = scsi_mmc_eject_media(p_env->gen.cdio);
429
cdio_warn("ioctl CDROMEJECT failed: %s\n",
430
strerror(eject_error));
434
/* force kernel to reread partition table when new disc inserted */
435
ret = ioctl(p_env->gen.fd, BLKRRPART);
438
cdio_warn ("Unknown CD-ROM (%d)\n", status);
442
cdio_warn ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno));
448
close(p_env->gen.fd);
454
Get disc type associated with the cd object.
457
get_discmode_linux (void *p_user_data)
459
_img_private_t *p_env = p_user_data;
463
/* See if this is a DVD. */
464
cdio_dvd_struct_t dvd; /* DVD READ STRUCT for layer 0. */
466
dvd.physical.type = CDIO_DVD_STRUCT_PHYSICAL;
467
dvd.physical.layer_num = 0;
468
if (0 == ioctl (p_env->gen.fd, DVD_READ_STRUCT, &dvd)) {
469
switch(dvd.physical.layer[0].book_type) {
470
case CDIO_DVD_BOOK_DVD_ROM: return CDIO_DISC_MODE_DVD_ROM;
471
case CDIO_DVD_BOOK_DVD_RAM: return CDIO_DISC_MODE_DVD_RAM;
472
case CDIO_DVD_BOOK_DVD_R: return CDIO_DISC_MODE_DVD_R;
473
case CDIO_DVD_BOOK_DVD_RW: return CDIO_DISC_MODE_DVD_RW;
474
case CDIO_DVD_BOOK_DVD_PR: return CDIO_DISC_MODE_DVD_PR;
475
case CDIO_DVD_BOOK_DVD_PRW: return CDIO_DISC_MODE_DVD_PRW;
476
default: return CDIO_DISC_MODE_DVD_OTHER;
480
i_discmode = ioctl (p_env->gen.fd, CDROM_DISC_STATUS);
482
if (i_discmode < 0) return CDIO_DISC_MODE_ERROR;
484
/* FIXME Need to add getting DVD types. */
487
return CDIO_DISC_MODE_CD_DA;
490
return CDIO_DISC_MODE_CD_DATA;
492
return CDIO_DISC_MODE_CD_MIXED;
495
return CDIO_DISC_MODE_CD_XA;
497
return CDIO_DISC_MODE_NO_INFO;
499
return CDIO_DISC_MODE_ERROR;
503
/* Check a drive to see if it is a CD-ROM
504
Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive
505
and -1 if no device exists .
508
is_cdrom_linux(const char *drive, char *mnttype)
512
struct cdrom_tochdr tochdr;
514
/* If it doesn't exist, return -1 */
515
if ( !cdio_is_device_quiet_generic(drive) ) {
519
/* If it does exist, verify that it's an available CD-ROM */
520
cdfd = open(drive, (O_RDONLY|O_NONBLOCK), 0);
522
if ( ioctl(cdfd, CDROMREADTOCHDR, &tochdr) != -1 ) {
527
/* Even if we can't read it, it might be mounted */
528
else if ( mnttype && (strcmp(mnttype, "iso9660") == 0) ) {
534
/* MMC driver to read audio sectors.
535
Can read only up to 25 blocks.
538
_read_audio_sectors_linux (void *p_user_data, void *buf, lsn_t lsn,
539
unsigned int nblocks)
541
_img_private_t *p_env = p_user_data;
542
return scsi_mmc_read_sectors( p_env->gen.cdio, buf, lsn,
543
CDIO_MMC_READ_TYPE_CDDA, nblocks);
546
/* Packet driver to read mode2 sectors.
547
Can read only up to 25 blocks.
550
_read_mode2_sectors_mmc (_img_private_t *p_env, void *p_buf, lba_t lba,
551
unsigned int nblocks, bool b_read_10)
553
scsi_mmc_cdb_t cdb = {{0, }};
555
CDIO_MMC_SET_READ_LBA(cdb.field, lba);
560
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_10);
561
CDIO_MMC_SET_READ_LENGTH16(cdb.field, nblocks);
563
if ((retval = scsi_mmc_set_blocksize (p_env->gen.cdio, M2RAW_SECTOR_SIZE)))
566
if ((retval = run_scsi_cmd_linux (p_env, 0,
567
scsi_mmc_get_cmd_len(cdb.field[0]),
570
M2RAW_SECTOR_SIZE * nblocks,
573
scsi_mmc_set_blocksize (p_env->gen.cdio, CDIO_CD_FRAMESIZE);
577
if ((retval = scsi_mmc_set_blocksize (p_env->gen.cdio, CDIO_CD_FRAMESIZE)))
581
cdb.field[1] = 0; /* sector size mode2 */
582
cdb.field[9] = 0x58; /* 2336 mode2 */
584
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_CD);
585
CDIO_MMC_SET_READ_LENGTH24(cdb.field, nblocks);
587
return run_scsi_cmd_linux (p_env, 0,
588
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
590
M2RAW_SECTOR_SIZE * nblocks, p_buf);
596
_read_mode2_sectors (_img_private_t *p_env, void *p_buf, lba_t lba,
597
unsigned int nblocks, bool b_read_10)
604
const unsigned nblocks2 = (nblocks > 25) ? 25 : nblocks;
605
void *p_buf2 = ((char *)p_buf ) + (l * M2RAW_SECTOR_SIZE);
607
retval |= _read_mode2_sectors_mmc (p_env, p_buf2, lba + l,
608
nblocks2, b_read_10);
621
Reads a single mode1 sector from cd device into data starting
622
from lsn. Returns 0 if no error.
625
_read_mode1_sector_linux (void *p_user_data, void *p_data, lsn_t lsn,
630
char buf[M2RAW_SECTOR_SIZE] = { 0, };
631
struct cdrom_msf *p_msf = (struct cdrom_msf *) &buf;
634
_img_private_t *p_env = p_user_data;
636
cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf);
637
msf->cdmsf_min0 = cdio_from_bcd8(_msf.m);
638
msf->cdmsf_sec0 = cdio_from_bcd8(_msf.s);
639
msf->cdmsf_frame0 = cdio_from_bcd8(_msf.f);
642
switch (p_env->access_mode)
645
cdio_warn ("no way to read mode1");
650
if (ioctl (p_env->gen.fd, CDROMREADMODE1, &buf) == -1)
654
/* exit (EXIT_FAILURE); */
660
if (_read_mode2_sectors (p_env->gen.fd, buf, lsn, 1,
661
(p_env->access_mode == _AM_READ_10)))
664
if (p_env->access_mode == _AM_READ_CD)
666
cdio_info ("READ_CD failed; switching to READ_10 mode...");
667
p_env->access_mode = _AM_READ_10;
672
cdio_info ("READ_10 failed; switching to ioctl(CDROMREADMODE2) mode...");
673
p_env->access_mode = _AM_IOCTL;
681
memcpy (data, buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE,
682
b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE);
685
return cdio_generic_read_form1_sector(p_user_data, p_data, lsn);
691
Reads nblocks of mode2 sectors from cd device into data starting
693
Returns 0 if no error.
696
_read_mode1_sectors_linux (void *p_user_data, void *p_data, lsn_t lsn,
697
bool b_form2, unsigned int nblocks)
699
_img_private_t *p_env = p_user_data;
702
unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
704
for (i = 0; i < nblocks; i++) {
705
if ( (retval = _read_mode1_sector_linux (p_env,
706
((char *)p_data) + (blocksize*i),
714
Reads a single mode2 sector from cd device into data starting
715
from lsn. Returns 0 if no error.
718
_read_mode2_sector_linux (void *p_user_data, void *p_data, lsn_t lsn,
721
char buf[M2RAW_SECTOR_SIZE] = { 0, };
722
struct cdrom_msf *msf = (struct cdrom_msf *) &buf;
725
_img_private_t *p_env = p_user_data;
727
cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf);
728
msf->cdmsf_min0 = cdio_from_bcd8(_msf.m);
729
msf->cdmsf_sec0 = cdio_from_bcd8(_msf.s);
730
msf->cdmsf_frame0 = cdio_from_bcd8(_msf.f);
733
switch (p_env->access_mode)
736
cdio_warn ("no way to read mode2");
741
if (ioctl (p_env->gen.fd, CDROMREADMODE2, &buf) == -1)
745
/* exit (EXIT_FAILURE); */
751
if (_read_mode2_sectors (p_env, buf, lsn, 1,
752
(p_env->access_mode == _AM_READ_10)))
755
if (p_env->access_mode == _AM_READ_CD)
757
cdio_info ("READ_CD failed; switching to READ_10 mode...");
758
p_env->access_mode = _AM_READ_10;
763
cdio_info ("READ_10 failed; switching to ioctl(CDROMREADMODE2) mode...");
764
p_env->access_mode = _AM_IOCTL;
773
memcpy (p_data, buf, M2RAW_SECTOR_SIZE);
775
memcpy (((char *)p_data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE);
781
Reads nblocks of mode2 sectors from cd device into data starting
783
Returns 0 if no error.
786
_read_mode2_sectors_linux (void *p_user_data, void *data, lsn_t lsn,
787
bool b_form2, unsigned int nblocks)
789
_img_private_t *p_env = p_user_data;
791
unsigned int i_blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
793
/* For each frame, pick out the data part we need */
794
for (i = 0; i < nblocks; i++) {
796
if ( (retval = _read_mode2_sector_linux (p_env,
797
((char *)data) + (i_blocksize*i),
805
Read and cache the CD's Track Table of Contents and track info.
806
Return false if successful or true if an error.
809
read_toc_linux (void *p_user_data)
811
_img_private_t *p_env = p_user_data;
814
/* read TOC header */
815
if ( ioctl(p_env->gen.fd, CDROMREADTOCHDR, &p_env->tochdr) == -1 ) {
816
cdio_warn("%s: %s\n",
817
"error in ioctl CDROMREADTOCHDR", strerror(errno));
821
p_env->gen.i_first_track = p_env->tochdr.cdth_trk0;
822
p_env->gen.i_tracks = p_env->tochdr.cdth_trk1;
824
/* read individual tracks */
825
for (i= p_env->gen.i_first_track; i<=p_env->gen.i_tracks; i++) {
826
p_env->tocent[i-p_env->gen.i_first_track].cdte_track = i;
827
p_env->tocent[i-p_env->gen.i_first_track].cdte_format = CDROM_MSF;
828
if ( ioctl(p_env->gen.fd, CDROMREADTOCENTRY,
829
&p_env->tocent[i-p_env->gen.i_first_track]) == -1 ) {
830
cdio_warn("%s %d: %s\n",
831
"error in ioctl CDROMREADTOCENTRY for track",
836
struct cdrom_msf0 *msf= &env->tocent[i-1].cdte_addr.msf;
838
fprintf (stdout, "--- track# %d (msf %2.2x:%2.2x:%2.2x)\n",
839
i, msf->minute, msf->second, msf->frame);
844
/* read the lead-out track */
845
p_env->tocent[p_env->gen.i_tracks].cdte_track = CDIO_CDROM_LEADOUT_TRACK;
846
p_env->tocent[p_env->gen.i_tracks].cdte_format = CDROM_MSF;
848
if (ioctl(p_env->gen.fd, CDROMREADTOCENTRY,
849
&p_env->tocent[p_env->gen.i_tracks]) == -1 ) {
850
cdio_warn("%s: %s\n",
851
"error in ioctl CDROMREADTOCENTRY for lead-out",
857
struct cdrom_msf0 *msf= &env->tocent[p_env->gen.i_tracks].cdte_addr.msf;
859
fprintf (stdout, "--- track# %d (msf %2.2x:%2.2x:%2.2x)\n",
860
i, msf->minute, msf->second, msf->frame);
863
p_env->gen.toc_init = true;
868
Run a SCSI MMC command.
870
cdio CD structure set by cdio_open().
871
i_timeout time in milliseconds we will wait for the command
872
to complete. If this value is -1, use the default
874
p_buf Buffer for data, both sending and receiving
876
e_direction direction the transfer is to go.
877
cdb CDB bytes. All values that are needed should be set on
878
input. We'll figure out what the right CDB length should be.
880
We return true if command completed successfully and false if not.
883
run_scsi_cmd_linux( const void *p_user_data,
884
unsigned int i_timeout_ms,
885
unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb,
886
scsi_mmc_direction_t e_direction,
887
unsigned int i_buf, /*in/out*/ void *p_buf )
889
const _img_private_t *p_env = p_user_data;
890
struct cdrom_generic_command cgc;
891
memset (&cgc, 0, sizeof (struct cdrom_generic_command));
892
memcpy(&cgc.cmd, p_cdb, i_cdb);
895
cgc.data_direction = (SCSI_MMC_DATA_READ == cgc.data_direction)
896
? CGC_DATA_READ : CGC_DATA_WRITE;
898
#ifdef HAVE_LINUX_CDROM_TIMEOUT
899
cgc.timeout = i_timeout_ms;
902
return ioctl (p_env->gen.fd, CDROM_SEND_PACKET, &cgc);
906
Return the size of the CD in logical block address (LBA) units.
909
stat_size_linux (void *p_user_data)
911
_img_private_t *p_env = p_user_data;
913
struct cdrom_tocentry tocent;
916
tocent.cdte_track = CDIO_CDROM_LEADOUT_TRACK;
917
tocent.cdte_format = CDROM_LBA;
918
if (ioctl (p_env->gen.fd, CDROMREADTOCENTRY, &tocent) == -1)
920
perror ("ioctl(CDROMREADTOCENTRY)");
924
size = tocent.cdte_addr.lba;
930
Set the arg "key" with "value" in the source device.
931
Currently "source" and "access-mode" are valid keys.
932
"source" sets the source device in I/O operations
933
"access-mode" sets the the method of CD access
935
0 is returned if no error was found, and nonzero if there as an error.
938
set_arg_linux (void *p_user_data, const char key[], const char value[])
940
_img_private_t *p_env = p_user_data;
942
if (!strcmp (key, "source"))
947
free (p_env->gen.source_name);
949
p_env->gen.source_name = strdup (value);
951
else if (!strcmp (key, "access-mode"))
953
return str_to_access_mode_linux(value);
961
/* checklist: /dev/cdrom, /dev/dvd /dev/hd?, /dev/scd? /dev/sr? */
962
static char checklist1[][40] = {
963
{"cdrom"}, {"dvd"}, {""}
965
static char checklist2[][40] = {
966
{"?a hd?"}, {"?0 scd?"}, {"?0 sr?"}, {""}
969
#endif /* HAVE_LINUX_CDROM */
972
Return an array of strings giving possible CD devices.
975
cdio_get_devices_linux (void)
977
#ifndef HAVE_LINUX_CDROM
984
char **drives = NULL;
985
unsigned int num_drives=0;
987
/* Scan the system for CD-ROM drives.
989
for ( i=0; strlen(checklist1[i]) > 0; ++i ) {
990
sprintf(drive, "/dev/%s", checklist1[i]);
991
if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) {
992
cdio_add_device_list(&drives, drive, &num_drives);
996
/* Now check the currently mounted CD drives */
997
if (NULL != (ret_drive = check_mounts_linux("/etc/mtab"))) {
998
cdio_add_device_list(&drives, ret_drive, &num_drives);
1002
/* Finally check possible mountable drives in /etc/fstab */
1003
if (NULL != (ret_drive = check_mounts_linux("/etc/fstab"))) {
1004
cdio_add_device_list(&drives, ret_drive, &num_drives);
1008
/* Scan the system for CD-ROM drives.
1009
Not always 100% reliable, so use the USE_MNTENT code above first.
1011
for ( i=0; strlen(checklist2[i]) > 0; ++i ) {
1015
for ( j=checklist2[i][1]; exists; ++j ) {
1016
sprintf(drive, "/dev/%s", &checklist2[i][3]);
1017
insert = strchr(drive, '?');
1018
if ( insert != NULL ) {
1021
if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) {
1022
cdio_add_device_list(&drives, drive, &num_drives);
1026
cdio_add_device_list(&drives, NULL, &num_drives);
1028
#endif /*HAVE_LINUX_CDROM*/
1032
Return a string containing the default CD device.
1035
cdio_get_default_device_linux(void)
1037
#ifndef HAVE_LINUX_CDROM
1046
/* Scan the system for CD-ROM drives.
1048
for ( i=0; strlen(checklist1[i]) > 0; ++i ) {
1049
sprintf(drive, "/dev/%s", checklist1[i]);
1050
if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) {
1051
return strdup(drive);
1055
/* Now check the currently mounted CD drives */
1056
if (NULL != (ret_drive = check_mounts_linux("/etc/mtab")))
1059
/* Finally check possible mountable drives in /etc/fstab */
1060
if (NULL != (ret_drive = check_mounts_linux("/etc/fstab")))
1063
/* Scan the system for CD-ROM drives.
1064
Not always 100% reliable, so use the USE_MNTENT code above first.
1066
for ( i=0; strlen(checklist2[i]) > 0; ++i ) {
1070
for ( j=checklist2[i][1]; exists; ++j ) {
1071
sprintf(drive, "/dev/%s", &checklist2[i][3]);
1072
insert = strchr(drive, '?');
1073
if ( insert != NULL ) {
1076
if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) {
1077
return(strdup(drive));
1082
#endif /*HAVE_LINUX_CDROM*/
1085
Initialization routine. This is the only thing that doesn't
1086
get called via a function pointer. In fact *we* are the
1087
ones to set that up.
1090
cdio_open_linux (const char *psz_source_name)
1092
return cdio_open_am_linux(psz_source_name, NULL);
1096
Initialization routine. This is the only thing that doesn't
1097
get called via a function pointer. In fact *we* are the
1098
ones to set that up.
1101
cdio_open_am_linux (const char *psz_orig_source, const char *access_mode)
1104
#ifdef HAVE_LINUX_CDROM
1106
_img_private_t *_data;
1109
cdio_funcs _funcs = {
1110
.eject_media = eject_media_linux,
1111
.free = cdio_generic_free,
1112
.get_arg = get_arg_linux,
1113
.get_cdtext = get_cdtext_generic,
1114
.get_default_device = cdio_get_default_device_linux,
1115
.get_devices = cdio_get_devices_linux,
1116
.get_discmode = get_discmode_linux,
1118
.get_drive_cap = get_drive_cap_linux,
1120
.get_drive_cap = scsi_mmc_get_drive_cap_generic,
1122
.get_first_track_num= get_first_track_num_generic,
1124
.get_mcn = get_mcn_linux,
1125
.get_num_tracks = get_num_tracks_generic,
1126
.get_track_format = get_track_format_linux,
1127
.get_track_green = get_track_green_linux,
1128
.get_track_lba = NULL, /* This could be implemented if need be. */
1129
.get_track_msf = get_track_msf_linux,
1130
.lseek = cdio_generic_lseek,
1131
.read = cdio_generic_read,
1132
.read_audio_sectors = _read_audio_sectors_linux,
1133
.read_mode1_sector = _read_mode1_sector_linux,
1134
.read_mode1_sectors = _read_mode1_sectors_linux,
1135
.read_mode2_sector = _read_mode2_sector_linux,
1136
.read_mode2_sectors = _read_mode2_sectors_linux,
1137
.read_toc = read_toc_linux,
1138
.run_scsi_mmc_cmd = run_scsi_cmd_linux,
1139
.set_arg = set_arg_linux,
1140
.stat_size = stat_size_linux
1143
_data = _cdio_malloc (sizeof (_img_private_t));
1145
_data->access_mode = str_to_access_mode_linux(access_mode);
1146
_data->gen.init = false;
1147
_data->gen.toc_init = false;
1149
_data->gen.b_cdtext_init = false;
1150
_data->gen.b_cdtext_error = false;
1152
if (NULL == psz_orig_source) {
1153
psz_source=cdio_get_default_device_linux();
1154
if (NULL == psz_source) return NULL;
1155
set_arg_linux(_data, "source", psz_source);
1158
if (cdio_is_device_generic(psz_orig_source))
1159
set_arg_linux(_data, "source", psz_orig_source);
1161
/* The below would be okay if all device drivers worked this way. */
1163
cdio_info ("source %s is not a device", psz_orig_source);
1169
ret = cdio_new ((void *)_data, &_funcs);
1170
if (ret == NULL) return NULL;
1172
if (cdio_generic_init(_data)) {
1175
cdio_generic_free (_data);
1181
#endif /* HAVE_LINUX_CDROM */
1186
cdio_have_linux (void)
1188
#ifdef HAVE_LINUX_CDROM
1192
#endif /* HAVE_LINUX_CDROM */