4 * low-level 'block device' for input to gdrom discs.
6 * Copyright (c) 2009 Nathan Keynes.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
29 #include "drivers/cdrom/sector.h"
30 #include "drivers/cdrom/cdrom.h"
31 #include "drivers/cdrom/ecc.h"
33 #define CHECK_READ(dev,lba,count) \
34 if( !IS_SECTOR_SOURCE(dev) ) { \
35 return CDROM_ERROR_NODISC; \
36 } else if( (dev)->size != 0 && ((lba) >= (dev)->size || (lba+block_count) > (dev)->size) ) { \
37 return CDROM_ERROR_BADREAD; \
40 /* Default read mode for each sector mode */
41 const uint32_t cdrom_sector_read_mode[] = { 0,
42 CDROM_READ_CDDA|CDROM_READ_DATA, CDROM_READ_MODE1|CDROM_READ_DATA,
43 CDROM_READ_MODE2|CDROM_READ_DATA, CDROM_READ_MODE2_FORM1|CDROM_READ_DATA,
44 CDROM_READ_MODE2_FORM1|CDROM_READ_DATA,
45 CDROM_READ_MODE2|CDROM_READ_DATA|CDROM_READ_SUBHEADER|CDROM_READ_ECC,
46 CDROM_READ_RAW, CDROM_READ_RAW,
47 CDROM_READ_CDDA|CDROM_READ_DATA};
49 /* Block size for each sector mode */
50 const uint32_t cdrom_sector_size[] = { 0, 2352, 2048, 2336, 2048, 2324, 2336, 2352, 2352, 2448 };
52 const char *cdrom_sector_mode_names[] = { "Unknown", "Audio", "Mode 1", "Mode 2", "Mode 2 Form 1", "Mode 2 Form 2",
53 "Mode 2 semiraw", "XA Raw", "Non-XA Raw", "CDDA+Subchan" };
56 /********************* Public functions *************************/
57 cdrom_error_t sector_source_read( sector_source_t device, cdrom_lba_t lba, cdrom_count_t block_count, unsigned char *buf )
59 CHECK_READ(device,lba,block_count);
60 return device->read_blocks(device, lba, block_count, buf);
63 cdrom_error_t sector_source_read_sectors( sector_source_t device, cdrom_lba_t lba, cdrom_count_t block_count, cdrom_read_mode_t mode,
64 unsigned char *buf, size_t *length )
66 CHECK_READ(device,lba,block_count);
67 return device->read_sectors(device, lba, block_count, mode, buf, length);
70 void sector_source_ref( sector_source_t device )
72 assert( IS_SECTOR_SOURCE(device) );
76 void sector_source_unref( sector_source_t device )
80 assert( IS_SECTOR_SOURCE(device) );
81 if( device->ref_count > 0 )
83 if( device->ref_count == 0 )
84 device->destroy(device);
87 void sector_source_release( sector_source_t device )
89 assert( IS_SECTOR_SOURCE(device) );
90 if( device->ref_count == 0 )
91 device->destroy(device);
94 /************************** Sector mangling ***************************/
96 * Private functions used to pack/unpack sectors, determine mode, and
97 * evaluate sector reads.
100 /** Basic data sector header structure */
101 struct cdrom_sector_header {
105 uint8_t subhead[8]; // Mode-2 XA sectors only
108 static const uint8_t cdrom_sync_data[12] = { 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0 };
110 /* Field combinations that are legal for mode 1 or mode 2 (formless) reads */
111 static const uint8_t legal_nonxa_fields[] =
112 { TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE,
113 TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE,
114 TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE,
115 FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE };
117 /* Field combinations that are legal for mode 2 form 1 or form 2 reads */
118 static const uint8_t legal_xa_fields[] =
119 { TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE,
120 TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE,
121 TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE,
122 FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE };
125 * Position per sector mode of each of the fields
126 * sync, header, subheader, data, ecc.
129 static const uint32_t sector_field_positions[][6] = {
130 { 0, 0, 0, 0, 0, 0 }, /* Unknown */
131 { 0, 0, 0, 0, 2352, 2352 }, /* CDDA */
132 { 0, 12, 16, 16, 2064, 2352 }, /* Mode 1 */
133 { 0, 12, 16, 16, 2352, 2352 }, /* Mode 2 formless */
134 { 0, 12, 16, 24, 2072, 2352 }, /* Mode 2 form 1 */
135 { 0, 12, 16, 24, 2352, 2352 }}; /* Mode 2 form 2 */
140 * Return CDROM_ERROR_OK if the given read mode + sector modes are compatible,
141 * otherwise either CDROM_ERROR_BADREADMODE or CDROM_ERROR_BADFIELD. Raw sector modes
142 * will return BADREADMODE, as it's impossible to tell.
144 * @param track_mode one of the CDROM_MODE* constants
145 * @param read_mode the full read mode
147 static cdrom_error_t is_legal_read( sector_mode_t sector_mode, cdrom_read_mode_t read_mode )
149 int read_sector_type = CDROM_READ_TYPE(read_mode);
150 int read_sector_fields = CDROM_READ_FIELDS(read_mode);
152 /* Check the sector type is consistent */
153 switch( read_sector_type ) {
154 case CDROM_READ_ANY: break;
155 case CDROM_READ_CDDA:
156 if( sector_mode != SECTOR_CDDA && sector_mode != SECTOR_CDDA_SUBCHANNEL )
157 return CDROM_ERROR_BADREADMODE;
159 case CDROM_READ_MODE1:
160 case CDROM_READ_MODE2_FORM1:
161 if( sector_mode != SECTOR_MODE1 && sector_mode != SECTOR_MODE2_FORM1 )
162 return CDROM_ERROR_BADREADMODE;
164 case CDROM_READ_MODE2_FORM2:
165 if( sector_mode != SECTOR_MODE2_FORM2 )
166 return CDROM_ERROR_BADREADMODE;
168 case CDROM_READ_MODE2:
169 if( sector_mode != SECTOR_MODE2_FORMLESS )
170 return CDROM_ERROR_BADREADMODE;
172 default: /* Illegal read mode */
173 return CDROM_ERROR_BADFIELD;
176 /* Check the fields requested are sane per MMC (non-contiguous regions prohibited) */
177 switch( sector_mode ) {
179 case SECTOR_CDDA_SUBCHANNEL:
180 return CDROM_ERROR_OK; /* Everything is OK */
181 case SECTOR_MODE2_FORM1:
182 case SECTOR_MODE2_FORM2:
183 if( !legal_xa_fields[read_sector_fields>>11] )
184 return CDROM_ERROR_BADFIELD;
186 return CDROM_ERROR_OK;
188 case SECTOR_MODE2_FORMLESS:
189 if( !legal_nonxa_fields[read_sector_fields>>11] )
190 return CDROM_ERROR_BADFIELD;
192 return CDROM_ERROR_OK;
194 return CDROM_ERROR_BADFIELD;
198 static sector_mode_t identify_sector( sector_mode_t raw_mode, unsigned char *buf )
200 struct cdrom_sector_header *header = (struct cdrom_sector_header *)buf;
203 case SECTOR_SEMIRAW_MODE2: /* XA sectors */
205 switch( header->mode ) {
206 case 1: return SECTOR_MODE1;
207 case 2: return ((header->subhead[2] & 0x20) == 0 ) ? SECTOR_MODE2_FORM1 : SECTOR_MODE2_FORM2;
208 default: return SECTOR_UNKNOWN;
210 case SECTOR_RAW_NONXA:
211 switch( header->mode ) {
212 case 1: return SECTOR_MODE1;
213 case 2: return SECTOR_MODE2_FORMLESS;
214 default: return SECTOR_UNKNOWN;
222 * Read a single raw sector from the device. Generate sync, ECC/EDC data etc where
225 static cdrom_error_t read_raw_sector( sector_source_t device, cdrom_lba_t lba, unsigned char *buf )
229 switch( device->mode ) {
231 case SECTOR_RAW_NONXA:
232 return device->read_blocks(device, lba, 1, buf);
233 case SECTOR_SEMIRAW_MODE2:
234 memcpy( buf, cdrom_sync_data, 12 );
235 cd_build_address(buf, SECTOR_MODE2_FORMLESS, lba);
236 return device->read_blocks(device, lba, 1, &buf[16]);
238 case SECTOR_MODE2_FORMLESS:
239 err = device->read_blocks(device, lba, 1, &buf[16]);
240 if( err == CDROM_ERROR_OK ) {
241 do_encode_L2( buf, device->mode, lba );
244 case SECTOR_MODE2_FORM1:
245 *((uint32_t *)(buf+16)) = *((uint32_t *)(buf+20)) = 0;
246 err = device->read_blocks(device, lba, 1, &buf[24]);
247 if( err == CDROM_ERROR_OK ) {
248 do_encode_L2( buf, device->mode, lba );
251 case SECTOR_MODE2_FORM2:
252 *((uint32_t *)(buf+16)) = *((uint32_t *)(buf+20)) = 0x00200000;
253 err = device->read_blocks(device, lba, 1, &buf[24]);
254 if( err == CDROM_ERROR_OK ) {
255 do_encode_L2( buf, device->mode, lba );
263 static cdrom_error_t extract_sector_fields( unsigned char *raw_sector, sector_mode_t mode, int fields, unsigned char *buf, size_t *length )
268 for( i=0; i<5; i++ ) {
269 if( fields & (0x8000>>i) ) {
271 start = sector_field_positions[mode][i];
272 else if( end != sector_field_positions[mode][i] )
273 return CDROM_ERROR_BADFIELD;
274 end = sector_field_positions[mode][i+1];
280 memcpy( buf, &raw_sector[start], end-start );
283 return CDROM_ERROR_OK;
286 cdrom_error_t sector_extract_from_raw( unsigned char *raw_sector, cdrom_read_mode_t mode, unsigned char *buf, size_t *length )
288 sector_mode_t sector_mode = identify_sector( SECTOR_RAW_XA, raw_sector );
289 if( sector_mode == SECTOR_UNKNOWN )
290 return CDROM_ERROR_BADREAD;
291 cdrom_error_t status = is_legal_read( sector_mode, mode );
292 if( status != CDROM_ERROR_OK )
294 return extract_sector_fields( raw_sector, sector_mode, CDROM_READ_FIELDS(mode), buf, length );
298 * This is horribly complicated by the need to handle mapping between all possible
299 * sector modes + read modes, but fortunately most sources can just supply
300 * a single block type and not care about the details here.
302 cdrom_error_t default_sector_source_read_sectors( sector_source_t device,
303 cdrom_lba_t lba, cdrom_count_t block_count, cdrom_read_mode_t mode,
304 unsigned char *buf, size_t *length )
306 unsigned char tmp[2448];
307 int read_sector_type = CDROM_READ_TYPE(mode);
308 int read_sector_fields = CDROM_READ_FIELDS(mode);
313 CHECK_READ(device, lba, count);
315 switch(device->mode) {
317 if( read_sector_type != CDROM_READ_ANY && read_sector_type != CDROM_READ_CDDA )
318 return CDROM_ERROR_BADREADMODE;
319 if( read_sector_fields != 0 ) {
320 len = block_count * CDROM_MAX_SECTOR_SIZE;
321 device->read_blocks( device, lba, block_count, buf );
324 case SECTOR_CDDA_SUBCHANNEL:
325 if( read_sector_type != CDROM_READ_ANY && read_sector_type != CDROM_READ_CDDA )
326 return CDROM_ERROR_BADREADMODE;
327 if( read_sector_fields != 0 ) {
328 len = block_count * 2352;
329 for( i=0; i<block_count; i++ ) {
330 device->read_blocks( device, lba+i, 1, tmp );
331 memcpy( &buf[2352*i], tmp, 2352 );
336 case SECTOR_RAW_NONXA:
337 case SECTOR_SEMIRAW_MODE2:
338 /* We (may) have to break the raw sector up into requested fields.
339 * Process sectors one at a time
341 for( i=0; i<block_count; i++ ) {
343 err = read_raw_sector( device, lba+i, tmp );
344 if( err != CDROM_ERROR_OK )
346 err = sector_extract_from_raw( tmp, mode, &buf[len], &tmplen );
347 if( err != CDROM_ERROR_OK )
352 default: /* Data-only blocks */
353 err = is_legal_read( device->mode, mode );
354 if( err != CDROM_ERROR_OK )
356 if( read_sector_fields == 0 ) { /* Read nothing */
359 return CDROM_ERROR_OK;
360 } else if( read_sector_fields == CDROM_READ_DATA ) {
363 *length = block_count * CDROM_SECTOR_SIZE(device->mode);
364 return device->read_blocks( device, lba, block_count, buf );
365 } else if( read_sector_fields == CDROM_READ_RAW ) {
366 for( i=0; i<block_count; i++ ) {
367 err = read_raw_sector( device, lba+i, &buf[2352*i] );
368 if( err != CDROM_ERROR_OK )
371 len = block_count * CDROM_MAX_SECTOR_SIZE;
373 for( i=0; i<block_count; i++ ) {
375 err = read_raw_sector( device, lba+i, tmp );
376 if( err != CDROM_ERROR_OK )
378 err = extract_sector_fields( tmp, device->mode, read_sector_fields, &buf[len], &tmplen );
379 if( err != CDROM_ERROR_OK )
387 return CDROM_ERROR_OK;
391 /************************ Base implementation *************************/
394 * Default destroy implementation - clears the tag and frees memory.
396 void default_sector_source_destroy( sector_source_t device )
398 assert( device != NULL && device->ref_count == 0 );
403 sector_source_t sector_source_init( sector_source_t device, sector_source_type_t type, sector_mode_t mode, cdrom_count_t size,
404 sector_source_read_fn_t readfn, sector_source_destroy_fn_t destroyfn )
406 device->tag = SECTOR_SOURCE_TAG;
407 device->ref_count = 0;
411 device->read_blocks = readfn;
412 device->read_sectors = default_sector_source_read_sectors;
413 if( destroyfn == NULL )
414 device->destroy = default_sector_source_destroy;
416 device->destroy = destroyfn;
420 /************************ Null device implementation *************************/
421 cdrom_error_t null_sector_source_read( sector_source_t device, cdrom_lba_t lba, cdrom_count_t block_count, unsigned char *buf )
423 memset( buf, 0, block_count*CDROM_SECTOR_SIZE(device->mode) );
424 return CDROM_ERROR_OK;
427 sector_source_t null_sector_source_new( sector_mode_t mode, cdrom_count_t size )
429 return sector_source_init( g_malloc(sizeof(struct sector_source)), NULL_SECTOR_SOURCE, mode, size,
430 null_sector_source_read, default_sector_source_destroy );
433 /************************ File device implementation *************************/
434 typedef struct file_sector_source {
435 struct sector_source dev;
437 uint32_t offset; /* offset in file where source begins */
438 sector_source_t ref; /* Parent source reference */
439 gboolean closeOnDestroy;
440 } *file_sector_source_t;
442 void file_sector_source_destroy( sector_source_t dev )
444 assert( IS_SECTOR_SOURCE_TYPE(dev,FILE_SECTOR_SOURCE) );
445 file_sector_source_t fdev = (file_sector_source_t)dev;
447 if( fdev->closeOnDestroy && fdev->file != NULL ) {
448 fclose( fdev->file );
450 sector_source_unref( fdev->ref );
452 default_sector_source_destroy(dev);
455 cdrom_error_t file_sector_source_read( sector_source_t dev, cdrom_lba_t lba, cdrom_count_t block_count, unsigned char *buf )
457 assert( IS_SECTOR_SOURCE_TYPE(dev,FILE_SECTOR_SOURCE) );
458 file_sector_source_t fdev = (file_sector_source_t)dev;
460 uint32_t off = fdev->offset + lba * CDROM_SECTOR_SIZE(dev->mode);
461 uint32_t size = block_count * CDROM_SECTOR_SIZE(dev->mode);
462 fseek( fdev->file, off, SEEK_SET );
464 size_t len = fread( buf, 1, size, fdev->file );
466 return CDROM_ERROR_READERROR;
467 } else if( len < size ) {
469 memset( buf + len, 0, size-len );
471 return CDROM_ERROR_OK;
474 sector_source_t file_sector_source_new( FILE *f, sector_mode_t mode, uint32_t offset,
475 cdrom_count_t sector_count, gboolean closeOnDestroy )
477 if( sector_count == FILE_SECTOR_FULL_FILE ) {
478 unsigned int sector_size = CDROM_SECTOR_SIZE(mode);
479 if( sector_size == 0 )
483 if( f == NULL || fstat( fileno(f), &st ) != 0 ) {
484 /* can't stat file? */
488 sector_count = (st.st_size + sector_size-1) / sector_size;
491 file_sector_source_t dev = g_malloc(sizeof(struct file_sector_source));
493 dev->offset = offset;
494 dev->closeOnDestroy = closeOnDestroy;
496 return sector_source_init( &dev->dev, FILE_SECTOR_SOURCE, mode, sector_count, file_sector_source_read, file_sector_source_destroy );
499 sector_source_t file_sector_source_new_full( FILE *f, sector_mode_t mode, gboolean closeOnDestroy )
501 return file_sector_source_new( f, mode, 0, FILE_SECTOR_FULL_FILE, closeOnDestroy );
504 sector_source_t file_sector_source_new_filename( const gchar *filename, sector_mode_t mode, uint32_t offset,
505 cdrom_count_t sector_count )
507 int fd = open( filename, O_RDONLY|O_NONBLOCK );
511 FILE *f = fdopen( fd , "ro" );
516 return file_sector_source_new( f, mode, offset, sector_count, TRUE );
520 sector_source_t file_sector_source_new_source( sector_source_t ref, sector_mode_t mode, uint32_t offset,
521 cdrom_count_t sector_count )
523 assert( IS_SECTOR_SOURCE_TYPE(ref,FILE_SECTOR_SOURCE) );
524 file_sector_source_t fref = (file_sector_source_t)ref;
526 sector_source_t source = file_sector_source_new( fref->file, mode, offset, sector_count, FALSE );
527 ((file_sector_source_t)source)->ref = ref;
528 sector_source_ref(ref);
532 FILE *file_sector_source_get_file( sector_source_t ref )
534 assert( IS_SECTOR_SOURCE_TYPE(ref,FILE_SECTOR_SOURCE) );
535 file_sector_source_t fref = (file_sector_source_t)ref;
539 int file_sector_source_get_fd( sector_source_t ref )
541 return fileno(file_sector_source_get_file(ref));
544 void file_sector_source_set_close_on_destroy( sector_source_t ref, gboolean closeOnDestroy )
546 assert( IS_SECTOR_SOURCE_TYPE(ref,FILE_SECTOR_SOURCE) );
547 file_sector_source_t fref = (file_sector_source_t)ref;
548 fref->closeOnDestroy = closeOnDestroy;
551 /********************** Temporary file implementation ************************/
553 * The tmpfile source behaves exactly like a regular file source, except that
554 * it creates a new temporary file, which is deleted on destruction or program
555 * exit. The file is initially empty, so the user will need to get the fd and
556 * write something to it before use.
559 typedef struct tmpfile_sector_source {
560 struct file_sector_source file;
561 const char *filename;
562 } *tmpfile_sector_source_t;
564 static GList *tmpfile_open_list = NULL;
565 static gboolean tmpfile_atexit_installed = 0; /* TRUE to indicate atexit hook is registered */
567 static void tmpfile_sector_close( sector_source_t dev )
569 assert( IS_SECTOR_SOURCE_TYPE(dev,FILE_SECTOR_SOURCE) );
570 tmpfile_sector_source_t fdev = (tmpfile_sector_source_t)dev;
572 if( fdev->file.file != NULL ) {
573 fclose( fdev->file.file );
574 fdev->file.file = NULL;
576 if( fdev->filename != NULL ) {
577 unlink(fdev->filename);
578 g_free((char *)fdev->filename);
579 fdev->filename = NULL;
585 * atexit hook to close any open tmpfiles - make sure they're deleted.
587 static void tmpfile_atexit_hook(void)
590 for( ptr = tmpfile_open_list; ptr != NULL; ptr = ptr->next ) {
591 sector_source_t source = (sector_source_t)ptr->data;
592 tmpfile_sector_close(source);
597 static void tmpfile_sector_source_destroy( sector_source_t dev )
599 tmpfile_sector_close(dev);
600 tmpfile_open_list = g_list_remove(tmpfile_open_list, dev);
601 default_sector_source_destroy(dev);
604 sector_source_t tmpfile_sector_source_new( sector_mode_t mode )
606 if( !tmpfile_atexit_installed ) {
607 atexit(tmpfile_atexit_hook);
610 gchar *tmpdir = getenv("TMPDIR");
611 if( tmpdir == NULL ) {
614 gchar *tempfile = get_filename_at(tmpdir, "cd.XXXXXXX");
615 int fd = mkstemp( tempfile );
621 FILE *f = fdopen( fd, "w+" );
629 tmpfile_sector_source_t dev = g_malloc0(sizeof(struct tmpfile_sector_source));
631 dev->filename = tempfile;
632 sector_source_t source = sector_source_init( &dev->file.dev, FILE_SECTOR_SOURCE, mode, 0, file_sector_source_read, tmpfile_sector_source_destroy );
633 tmpfile_open_list = g_list_append(tmpfile_open_list, source);
637 /************************ Memory device implementation *************************/
638 typedef struct mem_sector_source {
639 struct sector_source dev;
640 unsigned char *buffer;
641 gboolean freeOnDestroy;
642 } *mem_sector_source_t;
644 static void mem_sector_source_destroy( sector_source_t dev )
646 assert( IS_SECTOR_SOURCE_TYPE(dev,MEM_SECTOR_SOURCE) );
647 mem_sector_source_t mdev = (mem_sector_source_t)dev;
649 if( mdev->freeOnDestroy ) {
653 default_sector_source_destroy(dev);
656 static cdrom_error_t mem_sector_source_read( sector_source_t dev, cdrom_lba_t lba, cdrom_count_t block_count, unsigned char *buf )
658 assert( IS_SECTOR_SOURCE_TYPE(dev,MEM_SECTOR_SOURCE) );
659 mem_sector_source_t mdev = (mem_sector_source_t)dev;
661 if( (lba + block_count) >= dev->size )
662 return CDROM_ERROR_BADREAD;
663 uint32_t off = lba * CDROM_SECTOR_SIZE(dev->mode);
664 uint32_t size = block_count * CDROM_SECTOR_SIZE(dev->mode);
666 memcpy( buf, mdev->buffer + off, size );
667 return CDROM_ERROR_OK;
670 sector_source_t mem_sector_source_new_buffer( unsigned char *buffer, sector_mode_t mode,
671 cdrom_count_t sector_count, gboolean freeOnDestroy )
673 assert( mode != SECTOR_UNKNOWN );
674 assert( buffer != NULL );
675 mem_sector_source_t dev = g_malloc(sizeof(struct mem_sector_source));
676 dev->buffer = buffer;
677 dev->freeOnDestroy = freeOnDestroy;
678 return sector_source_init( &dev->dev, MEM_SECTOR_SOURCE, mode, sector_count, mem_sector_source_read, mem_sector_source_destroy );
681 sector_source_t mem_sector_source_new( sector_mode_t mode, cdrom_count_t sector_count )
683 return mem_sector_source_new_buffer( g_malloc( sector_count * CDROM_SECTOR_SIZE(mode) ), mode,
684 sector_count, TRUE );
687 unsigned char *mem_sector_source_get_buffer( sector_source_t dev )
689 assert( IS_SECTOR_SOURCE_TYPE(dev,MEM_SECTOR_SOURCE) );
690 mem_sector_source_t mdev = (mem_sector_source_t)dev;
695 /************************ Track device implementation *************************/
696 typedef struct track_sector_source {
697 struct sector_source dev;
700 } *track_sector_source_t;
702 cdrom_error_t track_sector_source_read_blocks( sector_source_t dev, cdrom_lba_t lba, cdrom_count_t count,
706 assert( IS_SECTOR_SOURCE_TYPE(dev,TRACK_SECTOR_SOURCE) );
707 assert( dev->mode != SECTOR_UNKNOWN );
708 track_sector_source_t tdev = (track_sector_source_t)dev;
709 return cdrom_disc_read_sectors( tdev->disc, lba + tdev->start_lba, count, CDROM_SECTOR_READ_MODE(dev->mode), out, &length );
712 cdrom_error_t track_sector_source_read_sectors( sector_source_t dev, cdrom_lba_t lba, cdrom_count_t count,
713 cdrom_read_mode_t mode, unsigned char *out, size_t *length )
715 assert( IS_SECTOR_SOURCE_TYPE(dev,TRACK_SECTOR_SOURCE) );
716 track_sector_source_t tdev = (track_sector_source_t)dev;
718 return cdrom_disc_read_sectors( tdev->disc, lba + tdev->start_lba, count, mode, out, length );
721 void track_sector_source_destroy( sector_source_t dev )
723 assert( IS_SECTOR_SOURCE_TYPE(dev,TRACK_SECTOR_SOURCE) );
724 track_sector_source_t tdev = (track_sector_source_t)dev;
725 sector_source_unref( &tdev->disc->source );
726 default_sector_source_destroy(dev);
729 sector_source_t track_sector_source_new( cdrom_disc_t disc, sector_mode_t mode, cdrom_lba_t lba, cdrom_count_t count )
734 track_sector_source_t dev = g_malloc(sizeof(struct track_sector_source));
736 dev->start_lba = lba;
737 sector_source_init( &dev->dev, TRACK_SECTOR_SOURCE, mode, count,
738 track_sector_source_read_blocks, track_sector_source_destroy );
739 dev->dev.read_sectors = track_sector_source_read_sectors;
740 sector_source_ref( &disc->source );
.