Search
lxdream.org :: lxdream/src/drivers/cdrom/sector.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/cdrom/sector.c
changeset 1097:d4807997e450
next1099:566cdeb157ec
author nkeynes
date Sun Jan 31 18:35:06 2010 +1000 (14 years ago)
permissions -rw-r--r--
last change Refactor CDROM host support
- Completely separate GDROM hardware (in gdrom/gdrom.c) from generic CDROM
support (now in drivers/cdrom)
- Add concept of 'sector sources' that can be mixed and matched to create
cdrom discs (makes support of arbitrary disc types much simpler)
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/drivers/cdrom/sector.c Sun Jan 31 18:35:06 2010 +1000
1.3 @@ -0,0 +1,581 @@
1.4 +/**
1.5 + * $Id$
1.6 + *
1.7 + * low-level 'block device' for input to gdrom discs.
1.8 + *
1.9 + * Copyright (c) 2009 Nathan Keynes.
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.14 + * (at your option) any later version.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful,
1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 + * GNU General Public License for more details.
1.20 + */
1.21 +
1.22 +#include <sys/stat.h>
1.23 +#include <glib/gmem.h>
1.24 +#include <assert.h>
1.25 +#include <stdlib.h>
1.26 +#include <stdio.h>
1.27 +#include <string.h>
1.28 +#include <unistd.h>
1.29 +#include <fcntl.h>
1.30 +
1.31 +#include "drivers/cdrom/sector.h"
1.32 +#include "drivers/cdrom/cdrom.h"
1.33 +#include "drivers/cdrom/ecc.h"
1.34 +
1.35 +#define CHECK_READ(dev,lba,count) \
1.36 + if( !IS_SECTOR_SOURCE(dev) ) { \
1.37 + return CDROM_ERROR_NODISC; \
1.38 + } else if( (lba) >= (dev)->size || (lba+block_count) > (dev)->size ) { \
1.39 + return CDROM_ERROR_BADREAD; \
1.40 + }
1.41 +
1.42 +/* Default read mode for each sector mode */
1.43 +const uint32_t cdrom_sector_read_mode[] = { 0,
1.44 + CDROM_READ_CDDA|CDROM_READ_DATA, CDROM_READ_MODE1|CDROM_READ_DATA,
1.45 + CDROM_READ_MODE2|CDROM_READ_DATA, CDROM_READ_MODE2_FORM1|CDROM_READ_DATA,
1.46 + CDROM_READ_MODE2_FORM1|CDROM_READ_DATA,
1.47 + CDROM_READ_MODE2|CDROM_READ_DATA|CDROM_READ_SUBHEADER|CDROM_READ_ECC,
1.48 + CDROM_READ_RAW, CDROM_READ_RAW };
1.49 +
1.50 +/* Block size for each sector mode */
1.51 +const uint32_t cdrom_sector_size[] = { 0, 2352, 2048, 2336, 2048, 2324, 2336, 2352, 2352 };
1.52 +
1.53 +const char *cdrom_sector_mode_names[] = { "Unknown", "Audio", "Mode 1", "Mode 2", "Mode 2 Form 1", "Mode 2 Form 2",
1.54 + "Mode 2 semiraw", "XA Raw", "Non-XA Raw" };
1.55 +
1.56 +
1.57 +/********************* Public functions *************************/
1.58 +cdrom_error_t sector_source_read( sector_source_t device, cdrom_lba_t lba, cdrom_count_t block_count, unsigned char *buf )
1.59 +{
1.60 + CHECK_READ(device,lba,block_count);
1.61 + return device->read_blocks(device, lba, block_count, buf);
1.62 +}
1.63 +
1.64 +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,
1.65 + unsigned char *buf, size_t *length )
1.66 +{
1.67 + CHECK_READ(device,lba,block_count);
1.68 + return device->read_sectors(device, lba, block_count, mode, buf, length);
1.69 +}
1.70 +
1.71 +void sector_source_ref( sector_source_t device )
1.72 +{
1.73 + assert( IS_SECTOR_SOURCE(device) );
1.74 + device->ref_count++;
1.75 +}
1.76 +
1.77 +void sector_source_unref( sector_source_t device )
1.78 +{
1.79 + if( device == NULL )
1.80 + return;
1.81 + assert( IS_SECTOR_SOURCE(device) );
1.82 + if( device->ref_count > 0 )
1.83 + device->ref_count--;
1.84 + if( device->ref_count == 0 )
1.85 + device->destroy(device);
1.86 +}
1.87 +
1.88 +void sector_source_release( sector_source_t device )
1.89 +{
1.90 + assert( IS_SECTOR_SOURCE(device) );
1.91 + if( device->ref_count == 0 )
1.92 + device->destroy(device);
1.93 +}
1.94 +
1.95 +/************************** Sector mangling ***************************/
1.96 +/*
1.97 + * Private functions used to pack/unpack sectors, determine mode, and
1.98 + * evaluate sector reads.
1.99 + */
1.100 +
1.101 +/** Basic data sector header structure */
1.102 +struct cdrom_sector_header {
1.103 + uint8_t sync[12];
1.104 + uint8_t msf[3];
1.105 + uint8_t mode;
1.106 + uint8_t subhead[8]; // Mode-2 XA sectors only
1.107 +};
1.108 +
1.109 +static const uint8_t cdrom_sync_data[12] = { 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0 };
1.110 +
1.111 +/* Field combinations that are legal for mode 1 or mode 2 (formless) reads */
1.112 +static const uint8_t legal_nonxa_fields[] =
1.113 +{ TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE,
1.114 + TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE,
1.115 + TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE,
1.116 + FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE };
1.117 +
1.118 +/* Field combinations that are legal for mode 2 form 1 or form 2 reads */
1.119 +static const uint8_t legal_xa_fields[] =
1.120 +{ TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE,
1.121 + TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE,
1.122 + TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE,
1.123 + FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE };
1.124 +
1.125 +/**
1.126 + * Position per sector mode of each of the fields
1.127 + * sync, header, subheader, data, ecc.
1.128 + *
1.129 + */
1.130 +static const uint32_t sector_field_positions[][6] = {
1.131 + { 0, 0, 0, 0, 0, 0 }, /* Unknown */
1.132 + { 0, 0, 0, 0, 2352, 2352 }, /* CDDA */
1.133 + { 0, 12, 16, 16, 2064, 2352 }, /* Mode 1 */
1.134 + { 0, 12, 16, 16, 2352, 2352 }, /* Mode 2 formless */
1.135 + { 0, 12, 16, 24, 2072, 2352 }, /* Mode 2 form 1 */
1.136 + { 0, 12, 16, 24, 2352, 2352 }}; /* Mode 2 form 2 */
1.137 +
1.138 +
1.139 +
1.140 +/**
1.141 + * Return CDROM_ERROR_OK if the given read mode + sector modes are compatible,
1.142 + * otherwise either CDROM_ERROR_BADREADMODE or CDROM_ERROR_BADFIELD. Raw sector modes
1.143 + * will return BADREADMODE, as it's impossible to tell.
1.144 + *
1.145 + * @param track_mode one of the CDROM_MODE* constants
1.146 + * @param read_mode the full read mode
1.147 + */
1.148 +static cdrom_error_t is_legal_read( sector_mode_t sector_mode, cdrom_read_mode_t read_mode )
1.149 +{
1.150 + int read_sector_type = CDROM_READ_TYPE(read_mode);
1.151 + int read_sector_fields = CDROM_READ_FIELDS(read_mode);
1.152 +
1.153 + /* Check the sector type is consistent */
1.154 + switch( read_sector_type ) {
1.155 + case CDROM_READ_ANY: break;
1.156 + case CDROM_READ_CDDA:
1.157 + if( sector_mode != SECTOR_CDDA )
1.158 + return CDROM_ERROR_BADREADMODE;
1.159 + break;
1.160 + case CDROM_READ_MODE1:
1.161 + case CDROM_READ_MODE2_FORM1:
1.162 + if( sector_mode != SECTOR_MODE1 && sector_mode != SECTOR_MODE2_FORM1 )
1.163 + return CDROM_ERROR_BADREADMODE;
1.164 + break;
1.165 + case CDROM_READ_MODE2_FORM2:
1.166 + if( sector_mode != SECTOR_MODE2_FORM2 )
1.167 + return CDROM_ERROR_BADREADMODE;
1.168 + break;
1.169 + case CDROM_READ_MODE2:
1.170 + if( sector_mode != SECTOR_MODE2_FORMLESS )
1.171 + return CDROM_ERROR_BADREADMODE;
1.172 + break;
1.173 + default: /* Illegal read mode */
1.174 + return CDROM_ERROR_BADFIELD;
1.175 + }
1.176 +
1.177 + /* Check the fields requested are sane per MMC (non-contiguous regions prohibited) */
1.178 + switch( sector_mode ) {
1.179 + case SECTOR_CDDA:
1.180 + return CDROM_ERROR_OK; /* Everything is OK */
1.181 + case SECTOR_MODE2_FORM1:
1.182 + case SECTOR_MODE2_FORM2:
1.183 + if( !legal_xa_fields[read_sector_fields>>11] )
1.184 + return CDROM_ERROR_BADFIELD;
1.185 + else
1.186 + return CDROM_ERROR_OK;
1.187 + case SECTOR_MODE1:
1.188 + case SECTOR_MODE2_FORMLESS:
1.189 + if( !legal_nonxa_fields[read_sector_fields>>11] )
1.190 + return CDROM_ERROR_BADFIELD;
1.191 + else
1.192 + return CDROM_ERROR_OK;
1.193 + default:
1.194 + return CDROM_ERROR_BADFIELD;
1.195 + }
1.196 +}
1.197 +
1.198 +static sector_mode_t identify_sector( sector_mode_t raw_mode, unsigned char *buf )
1.199 +{
1.200 + struct cdrom_sector_header *header = (struct cdrom_sector_header *)buf;
1.201 +
1.202 + switch( raw_mode ) {
1.203 + case SECTOR_SEMIRAW_MODE2: /* XA sectors */
1.204 + case SECTOR_RAW_XA:
1.205 + switch( header->mode ) {
1.206 + case 1: return SECTOR_MODE1;
1.207 + case 2: return ((header->subhead[2] & 0x20) == 0 ) ? SECTOR_MODE2_FORM1 : SECTOR_MODE2_FORM2;
1.208 + default: return SECTOR_UNKNOWN;
1.209 + }
1.210 + case SECTOR_RAW_NONXA:
1.211 + switch( header->mode ) {
1.212 + case 1: return SECTOR_MODE1;
1.213 + case 2: return SECTOR_MODE2_FORMLESS;
1.214 + default: return SECTOR_UNKNOWN;
1.215 + }
1.216 + default:
1.217 + return raw_mode;
1.218 + }
1.219 +}
1.220 +
1.221 +/**
1.222 + * Read a single raw sector from the device. Generate sync, ECC/EDC data etc where
1.223 + * necessary.
1.224 + */
1.225 +static cdrom_error_t read_raw_sector( sector_source_t device, cdrom_lba_t lba, unsigned char *buf )
1.226 +{
1.227 + cdrom_error_t err;
1.228 +
1.229 + switch( device->mode ) {
1.230 + case SECTOR_RAW_XA:
1.231 + case SECTOR_RAW_NONXA:
1.232 + return device->read_blocks(device, lba, 1, buf);
1.233 + case SECTOR_SEMIRAW_MODE2:
1.234 + memcpy( buf, cdrom_sync_data, 12 );
1.235 + cd_build_address(buf, SECTOR_MODE2_FORMLESS, lba);
1.236 + return device->read_blocks(device, lba, 1, &buf[16]);
1.237 + case SECTOR_MODE1:
1.238 + case SECTOR_MODE2_FORMLESS:
1.239 + err = device->read_blocks(device, lba, 1, &buf[16]);
1.240 + if( err == CDROM_ERROR_OK ) {
1.241 + do_encode_L2( buf, device->mode, lba );
1.242 + }
1.243 + return err;
1.244 + case SECTOR_MODE2_FORM1:
1.245 + *((uint32_t *)(buf+16)) = *((uint32_t *)(buf+20)) = 0;
1.246 + err = device->read_blocks(device, lba, 1, &buf[24]);
1.247 + if( err == CDROM_ERROR_OK ) {
1.248 + do_encode_L2( buf, device->mode, lba );
1.249 + }
1.250 + return err;
1.251 + case SECTOR_MODE2_FORM2:
1.252 + *((uint32_t *)(buf+16)) = *((uint32_t *)(buf+20)) = 0x00200000;
1.253 + err = device->read_blocks(device, lba, 1, &buf[24]);
1.254 + if( err == CDROM_ERROR_OK ) {
1.255 + do_encode_L2( buf, device->mode, lba );
1.256 + }
1.257 + return err;
1.258 + default:
1.259 + abort();
1.260 + }
1.261 +}
1.262 +
1.263 +static cdrom_error_t extract_sector_fields( unsigned char *raw_sector, sector_mode_t mode, int fields, unsigned char *buf, size_t *length )
1.264 +{
1.265 + int start=-1,end=0;
1.266 + int i;
1.267 +
1.268 + for( i=0; i<5; i++ ) {
1.269 + if( fields & (0x8000>>i) ) {
1.270 + if( start == -1 )
1.271 + start = sector_field_positions[mode][i];
1.272 + else if( end != sector_field_positions[mode][i] )
1.273 + return CDROM_ERROR_BADFIELD;
1.274 + end = sector_field_positions[mode][i+1];
1.275 + }
1.276 + }
1.277 + if( start == -1 ) {
1.278 + *length = 0;
1.279 + } else {
1.280 + memcpy( buf, &raw_sector[start], end-start );
1.281 + *length = end-start;
1.282 + }
1.283 + return CDROM_ERROR_OK;
1.284 +}
1.285 +
1.286 +cdrom_error_t sector_extract_from_raw( unsigned char *raw_sector, cdrom_read_mode_t mode, unsigned char *buf, size_t *length )
1.287 +{
1.288 + sector_mode_t sector_mode = identify_sector( SECTOR_RAW_XA, raw_sector );
1.289 + if( sector_mode == SECTOR_UNKNOWN )
1.290 + return CDROM_ERROR_BADREAD;
1.291 + cdrom_error_t status = is_legal_read( sector_mode, mode );
1.292 + if( status != CDROM_ERROR_OK )
1.293 + return status;
1.294 + return extract_sector_fields( raw_sector, sector_mode, CDROM_READ_FIELDS(mode), buf, length );
1.295 +}
1.296 +
1.297 +/**
1.298 + * This is horribly complicated by the need to handle mapping between all possible
1.299 + * sector modes + read modes, but fortunately most sources can just supply
1.300 + * a single block type and not care about the details here.
1.301 + */
1.302 +cdrom_error_t default_sector_source_read_sectors( sector_source_t device,
1.303 + cdrom_lba_t lba, cdrom_count_t block_count, cdrom_read_mode_t mode,
1.304 + unsigned char *buf, size_t *length )
1.305 +{
1.306 + unsigned char tmp[CDROM_MAX_SECTOR_SIZE];
1.307 + int read_sector_type = CDROM_READ_TYPE(mode);
1.308 + int read_sector_fields = CDROM_READ_FIELDS(mode);
1.309 + int i;
1.310 + size_t len = 0;
1.311 + cdrom_error_t err;
1.312 +
1.313 + CHECK_READ(device, lba, count);
1.314 +
1.315 + switch(device->mode) {
1.316 + case SECTOR_CDDA:
1.317 + if( read_sector_type != CDROM_READ_ANY && read_sector_type != CDROM_READ_CDDA )
1.318 + return CDROM_ERROR_BADREADMODE;
1.319 + if( read_sector_fields != 0 ) {
1.320 + len = block_count * CDROM_MAX_SECTOR_SIZE;
1.321 + device->read_blocks( device, lba, block_count, buf );
1.322 + }
1.323 + break;
1.324 + case SECTOR_RAW_XA:
1.325 + case SECTOR_RAW_NONXA:
1.326 + case SECTOR_SEMIRAW_MODE2:
1.327 + /* We (may) have to break the raw sector up into requested fields.
1.328 + * Process sectors one at a time
1.329 + */
1.330 + for( i=0; i<block_count; i++ ) {
1.331 + size_t tmplen;
1.332 + err = read_raw_sector( device, lba+i, tmp );
1.333 + if( err != CDROM_ERROR_OK )
1.334 + return err;
1.335 + err = sector_extract_from_raw( tmp, mode, &buf[len], &tmplen );
1.336 + if( err != CDROM_ERROR_OK )
1.337 + return err;
1.338 + len += tmplen;
1.339 + }
1.340 + break;
1.341 + default: /* Data-only blocks */
1.342 + err = is_legal_read( device->mode, mode );
1.343 + if( err != CDROM_ERROR_OK )
1.344 + return err;
1.345 + if( read_sector_fields == 0 ) { /* Read nothing */
1.346 + *length = 0;
1.347 + return CDROM_ERROR_OK;
1.348 + } else if( read_sector_fields == CDROM_READ_DATA ) {
1.349 + /* Data-only */
1.350 + *length = block_count * CDROM_SECTOR_SIZE(device->mode);
1.351 + return device->read_blocks( device, lba, block_count, buf );
1.352 + } else if( read_sector_fields == CDROM_READ_RAW ) {
1.353 + for( i=0; i<block_count; i++ ) {
1.354 + err = read_raw_sector( device, lba+i, &buf[2352*i] );
1.355 + if( err != CDROM_ERROR_OK )
1.356 + return err;
1.357 + }
1.358 + len = block_count * CDROM_MAX_SECTOR_SIZE;
1.359 + } else {
1.360 + for( i=0; i<block_count; i++ ) {
1.361 + size_t tmplen;
1.362 + err = read_raw_sector( device, lba+i, tmp );
1.363 + if( err != CDROM_ERROR_OK )
1.364 + return err;
1.365 + err = extract_sector_fields( tmp, device->mode, read_sector_fields, &buf[len], &tmplen );
1.366 + if( err != CDROM_ERROR_OK )
1.367 + return err;
1.368 + len += tmplen;
1.369 + }
1.370 + }
1.371 + }
1.372 + *length = len;
1.373 + return CDROM_ERROR_OK;
1.374 +
1.375 +}
1.376 +
1.377 +/************************ Base implementation *************************/
1.378 +
1.379 +/**
1.380 + * Default destroy implementation - clears the tag and frees memory.
1.381 + */
1.382 +void default_sector_source_destroy( sector_source_t device )
1.383 +{
1.384 + assert( device != NULL && device->ref_count == 0 );
1.385 + device->tag = 0;
1.386 + g_free( device );
1.387 +}
1.388 +
1.389 +sector_source_t sector_source_init( sector_source_t device, sector_source_type_t type, sector_mode_t mode, cdrom_count_t size,
1.390 + sector_source_read_fn_t readfn, sector_source_destroy_fn_t destroyfn )
1.391 +{
1.392 + device->tag = SECTOR_SOURCE_TAG;
1.393 + device->ref_count = 0;
1.394 + device->type = type;
1.395 + device->mode = mode;
1.396 + device->size = size;
1.397 + device->read_blocks = readfn;
1.398 + device->read_sectors = default_sector_source_read_sectors;
1.399 + if( destroyfn == NULL )
1.400 + device->destroy = default_sector_source_destroy;
1.401 + else
1.402 + device->destroy = destroyfn;
1.403 + return device;
1.404 +}
1.405 +
1.406 +/************************ Null device implementation *************************/
1.407 +cdrom_error_t null_sector_source_read( sector_source_t device, cdrom_lba_t lba, cdrom_count_t block_count, unsigned char *buf )
1.408 +{
1.409 + memset( buf, 0, block_count*CDROM_SECTOR_SIZE(device->mode) );
1.410 + return CDROM_ERROR_OK;
1.411 +}
1.412 +
1.413 +sector_source_t null_sector_source_new( sector_mode_t mode, cdrom_count_t size )
1.414 +{
1.415 + return sector_source_init( g_malloc(sizeof(struct sector_source)), NULL_SECTOR_SOURCE, mode, size,
1.416 + null_sector_source_read, default_sector_source_destroy );
1.417 +}
1.418 +
1.419 +/************************ File device implementation *************************/
1.420 +typedef struct file_sector_source {
1.421 + struct sector_source dev;
1.422 + FILE *file;
1.423 + uint32_t offset; /* offset in file where source begins */
1.424 + sector_source_t ref; /* Parent source reference */
1.425 + gboolean closeOnDestroy;
1.426 +} *file_sector_source_t;
1.427 +
1.428 +void file_sector_source_destroy( sector_source_t dev )
1.429 +{
1.430 + assert( IS_SECTOR_SOURCE_TYPE(dev,FILE_SECTOR_SOURCE) );
1.431 + file_sector_source_t fdev = (file_sector_source_t)dev;
1.432 +
1.433 + if( fdev->closeOnDestroy && fdev->file != NULL ) {
1.434 + fclose( fdev->file );
1.435 + }
1.436 + sector_source_unref( fdev->ref );
1.437 + fdev->file = NULL;
1.438 + default_sector_source_destroy(dev);
1.439 +}
1.440 +
1.441 +cdrom_error_t file_sector_source_read( sector_source_t dev, cdrom_lba_t lba, cdrom_count_t block_count, unsigned char *buf )
1.442 +{
1.443 + assert( IS_SECTOR_SOURCE_TYPE(dev,FILE_SECTOR_SOURCE) );
1.444 + file_sector_source_t fdev = (file_sector_source_t)dev;
1.445 +
1.446 + uint32_t off = fdev->offset + lba * CDROM_SECTOR_SIZE(dev->mode);
1.447 + uint32_t size = block_count * CDROM_SECTOR_SIZE(dev->mode);
1.448 + fseek( fdev->file, off, SEEK_SET );
1.449 +
1.450 + size_t len = fread( buf, 1, size, fdev->file );
1.451 + if( len == -1 ) {
1.452 + return CDROM_ERROR_READERROR;
1.453 + } else if( len < size ) {
1.454 + /* zero-fill */
1.455 + memset( buf + len, 0, size-len );
1.456 + }
1.457 + return CDROM_ERROR_OK;
1.458 +}
1.459 +
1.460 +sector_source_t file_sector_source_new( FILE *f, sector_mode_t mode, uint32_t offset,
1.461 + cdrom_count_t sector_count, gboolean closeOnDestroy )
1.462 +{
1.463 + if( sector_count == FILE_SECTOR_FULL_FILE ) {
1.464 + unsigned int sector_size = CDROM_SECTOR_SIZE(mode);
1.465 + if( sector_size == 0 )
1.466 + sector_size = 2048;
1.467 + struct stat st;
1.468 +
1.469 + if( f == NULL || fstat( fileno(f), &st ) != 0 ) {
1.470 + /* can't stat file? */
1.471 + return NULL;
1.472 + }
1.473 +
1.474 + sector_count = (st.st_size + sector_size-1) / sector_size;
1.475 + }
1.476 +
1.477 + file_sector_source_t dev = g_malloc(sizeof(struct file_sector_source));
1.478 + dev->file = f;
1.479 + dev->offset = offset;
1.480 + dev->closeOnDestroy = closeOnDestroy;
1.481 + dev->ref = NULL;
1.482 + return sector_source_init( &dev->dev, FILE_SECTOR_SOURCE, mode, sector_count, file_sector_source_read, file_sector_source_destroy );
1.483 +}
1.484 +
1.485 +sector_source_t file_sector_source_new_full( FILE *f, sector_mode_t mode, gboolean closeOnDestroy )
1.486 +{
1.487 + return file_sector_source_new( f, mode, 0, FILE_SECTOR_FULL_FILE, closeOnDestroy );
1.488 +}
1.489 +
1.490 +sector_source_t file_sector_source_new_filename( const gchar *filename, sector_mode_t mode, uint32_t offset,
1.491 + cdrom_count_t sector_count )
1.492 +{
1.493 + int fd = open( filename, O_RDONLY|O_NONBLOCK );
1.494 + if( fd == -1 ) {
1.495 + return NULL;
1.496 + }
1.497 + FILE *f = fdopen( fd , "ro" );
1.498 + if( f == NULL ) {
1.499 + close(fd);
1.500 + return NULL;
1.501 + } else {
1.502 + return file_sector_source_new( f, mode, offset, sector_count, TRUE );
1.503 + }
1.504 +}
1.505 +
1.506 +sector_source_t file_sector_source_new_source( sector_source_t ref, sector_mode_t mode, uint32_t offset,
1.507 + cdrom_count_t sector_count )
1.508 +{
1.509 + assert( IS_SECTOR_SOURCE_TYPE(ref,FILE_SECTOR_SOURCE) );
1.510 + file_sector_source_t fref = (file_sector_source_t)ref;
1.511 +
1.512 + sector_source_t source = file_sector_source_new( fref->file, mode, offset, sector_count, FALSE );
1.513 + ((file_sector_source_t)source)->ref = ref;
1.514 + sector_source_ref(ref);
1.515 + return source;
1.516 +}
1.517 +
1.518 +FILE *file_sector_source_get_file( sector_source_t ref )
1.519 +{
1.520 + assert( IS_SECTOR_SOURCE_TYPE(ref,FILE_SECTOR_SOURCE) );
1.521 + file_sector_source_t fref = (file_sector_source_t)ref;
1.522 + return fref->file;
1.523 +}
1.524 +
1.525 +int file_sector_source_get_fd( sector_source_t ref )
1.526 +{
1.527 + return fileno(file_sector_source_get_file(ref));
1.528 +}
1.529 +
1.530 +void file_sector_source_set_close_on_destroy( sector_source_t ref, gboolean closeOnDestroy )
1.531 +{
1.532 + assert( IS_SECTOR_SOURCE_TYPE(ref,FILE_SECTOR_SOURCE) );
1.533 + file_sector_source_t fref = (file_sector_source_t)ref;
1.534 + fref->closeOnDestroy = closeOnDestroy;
1.535 +}
1.536 +
1.537 +/************************ Track device implementation *************************/
1.538 +typedef struct track_sector_source {
1.539 + struct sector_source dev;
1.540 + cdrom_disc_t disc;
1.541 + uint32_t start_lba;
1.542 +} *track_sector_source_t;
1.543 +
1.544 +cdrom_error_t track_sector_source_read_blocks( sector_source_t dev, cdrom_lba_t lba, cdrom_count_t count,
1.545 + unsigned char *out )
1.546 +{
1.547 + size_t length;
1.548 + assert( IS_SECTOR_SOURCE_TYPE(dev,TRACK_SECTOR_SOURCE) );
1.549 + assert( dev->mode != SECTOR_UNKNOWN );
1.550 + track_sector_source_t tdev = (track_sector_source_t)dev;
1.551 + return cdrom_disc_read_sectors( tdev->disc, lba + tdev->start_lba, count, CDROM_SECTOR_READ_MODE(dev->mode), out, &length );
1.552 +}
1.553 +
1.554 +cdrom_error_t track_sector_source_read_sectors( sector_source_t dev, cdrom_lba_t lba, cdrom_count_t count,
1.555 + cdrom_read_mode_t mode, unsigned char *out, size_t *length )
1.556 +{
1.557 + assert( IS_SECTOR_SOURCE_TYPE(dev,TRACK_SECTOR_SOURCE) );
1.558 + track_sector_source_t tdev = (track_sector_source_t)dev;
1.559 +
1.560 + return cdrom_disc_read_sectors( tdev->disc, lba + tdev->start_lba, count, mode, out, length );
1.561 +}
1.562 +
1.563 +void track_sector_source_destroy( sector_source_t dev )
1.564 +{
1.565 + assert( IS_SECTOR_SOURCE_TYPE(dev,TRACK_SECTOR_SOURCE) );
1.566 + track_sector_source_t tdev = (track_sector_source_t)dev;
1.567 + sector_source_unref( &tdev->disc->source );
1.568 + default_sector_source_destroy(dev);
1.569 +}
1.570 +
1.571 +sector_source_t track_sector_source_new( cdrom_disc_t disc, sector_mode_t mode, cdrom_lba_t lba, cdrom_count_t count )
1.572 +{
1.573 + if( disc == NULL ) {
1.574 + return NULL;
1.575 + }
1.576 + track_sector_source_t dev = g_malloc(sizeof(struct track_sector_source));
1.577 + dev->disc = disc;
1.578 + dev->start_lba = lba;
1.579 + sector_source_init( &dev->dev, TRACK_SECTOR_SOURCE, mode, count,
1.580 + track_sector_source_read_blocks, track_sector_source_destroy );
1.581 + dev->dev.read_sectors = track_sector_source_read_sectors;
1.582 + sector_source_ref( &disc->source );
1.583 + return &dev->dev;
1.584 +}
.