nkeynes@1097: /** nkeynes@1097: * $Id$ nkeynes@1097: * nkeynes@1097: * low-level 'block device' for input to cdrom discs. nkeynes@1097: * nkeynes@1097: * Copyright (c) 2009 Nathan Keynes. nkeynes@1097: * nkeynes@1097: * This program is free software; you can redistribute it and/or modify nkeynes@1097: * it under the terms of the GNU General Public License as published by nkeynes@1097: * the Free Software Foundation; either version 2 of the License, or nkeynes@1097: * (at your option) any later version. nkeynes@1097: * nkeynes@1097: * This program is distributed in the hope that it will be useful, nkeynes@1097: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@1097: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@1097: * GNU General Public License for more details. nkeynes@1097: */ nkeynes@1097: nkeynes@1097: #ifndef cdrom_sector_H nkeynes@1097: #define cdrom_sector_H 1 nkeynes@1097: nkeynes@1097: #include nkeynes@1296: #include nkeynes@1097: #include "drivers/cdrom/defs.h" nkeynes@1097: nkeynes@1097: #ifdef __cplusplus nkeynes@1097: extern "C" { nkeynes@1097: #endif nkeynes@1097: nkeynes@1097: /******************************** Sector Source ******************************/ nkeynes@1097: #define SECTOR_SOURCE_TAG 0x42444556 nkeynes@1097: typedef struct sector_source *sector_source_t; nkeynes@1097: typedef enum { nkeynes@1097: NULL_SECTOR_SOURCE, nkeynes@1097: FILE_SECTOR_SOURCE, nkeynes@1107: MEM_SECTOR_SOURCE, nkeynes@1097: DISC_SECTOR_SOURCE, nkeynes@1097: TRACK_SECTOR_SOURCE nkeynes@1097: } sector_source_type_t; nkeynes@1097: nkeynes@1097: typedef cdrom_error_t (*sector_source_read_fn_t)(sector_source_t, cdrom_lba_t, cdrom_count_t, unsigned char *outbuf); nkeynes@1097: typedef cdrom_error_t (*sector_source_read_sectors_fn_t)(sector_source_t, cdrom_lba_t, cdrom_count_t, cdrom_read_mode_t mode, nkeynes@1097: unsigned char *outbuf, size_t *length); nkeynes@1097: typedef void (*sector_source_destroy_fn_t)(sector_source_t); nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * A 'sector source' is a read-only random-access data source that supports nkeynes@1097: * reads of arbitrary blocks within their capacity. A block device has a nkeynes@1097: * defined mode, block size, and block count. nkeynes@1097: * nkeynes@1097: * Source are ref-counted, and automatically destroyed when the reference nkeynes@1097: * count reaches 0. nkeynes@1097: */ nkeynes@1097: struct sector_source { nkeynes@1097: uint32_t tag; /* sector source tag */ nkeynes@1097: uint32_t ref_count; /* Reference count. Initialized to 0 */ nkeynes@1097: sector_source_type_t type; nkeynes@1097: nkeynes@1097: sector_mode_t mode; /* Implies sector size. */ nkeynes@1107: cdrom_count_t size; /* Block count */ nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Read blocks from the device using the native block size. nkeynes@1097: * @param buf Buffer to receive the blocks nkeynes@1097: * @param block First block to transfer (numbered from 0) nkeynes@1097: * @param block_count number of blocks to transfer. nkeynes@1097: * @return 0 on success, otherwise an error code. nkeynes@1097: */ nkeynes@1097: sector_source_read_fn_t read_blocks; nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Read sectors from the device using the specified read mode, performing any nkeynes@1097: * necessary conversions. nkeynes@1097: */ nkeynes@1097: sector_source_read_sectors_fn_t read_sectors; nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Release all resources and memory used by the device (note should never nkeynes@1097: * be called directly nkeynes@1097: */ nkeynes@1097: sector_source_destroy_fn_t destroy; nkeynes@1097: nkeynes@1097: }; nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Block device that always returns zeros. nkeynes@1097: */ nkeynes@1097: sector_source_t null_sector_source_new( sector_mode_t mode, cdrom_count_t size ); nkeynes@1097: nkeynes@1097: #define FILE_SECTOR_FULL_FILE ((cdrom_count_t)-1) nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * File reader. Last block is 0-padded. nkeynes@1097: */ nkeynes@1097: sector_source_t file_sector_source_new_filename( const gchar *filename, sector_mode_t mode, nkeynes@1097: uint32_t offset, cdrom_count_t sector_count ); nkeynes@1097: sector_source_t file_sector_source_new( FILE *f, sector_mode_t mode, uint32_t offset, cdrom_count_t sector_count, nkeynes@1097: gboolean closeOnDestroy ); nkeynes@1097: sector_source_t file_sector_source_new_full( FILE *f, sector_mode_t mode, gboolean closeOnDestroy ); nkeynes@1097: nkeynes@1097: /** nkeynes@1107: * Temp-file creator - initially empty. Creates a file in the system temp dir, nkeynes@1107: * unlinked on destruction or program exit. nkeynes@1107: */ nkeynes@1107: sector_source_t tmpfile_sector_source_new( sector_mode_t mode ); nkeynes@1107: nkeynes@1107: /** nkeynes@1097: * Construct a file source that shares its file descriptor with another nkeynes@1097: * file source. nkeynes@1097: */ nkeynes@1097: sector_source_t file_sector_source_new_source( sector_source_t ref, sector_mode_t mode, uint32_t offset, nkeynes@1097: cdrom_count_t sector_count ); nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Change the value of the source's closeOnDestroy flag nkeynes@1097: */ nkeynes@1097: void file_sector_source_set_close_on_destroy( sector_source_t ref, gboolean closeOnDestroy ); nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Retrieve the source's underlying FILE nkeynes@1097: */ nkeynes@1097: FILE *file_sector_source_get_file( sector_source_t ref ); nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Retrieve the source's underlying file descriptor nkeynes@1097: */ nkeynes@1097: int file_sector_source_get_fd( sector_source_t ref ); nkeynes@1097: nkeynes@1107: /** Construct a memory source with the given mode and size */ nkeynes@1107: sector_source_t mem_sector_source_new( sector_mode_t mode, cdrom_count_t size ); nkeynes@1107: nkeynes@1107: /** nkeynes@1107: * Construct a memory source using the supplied buffer for data. nkeynes@1107: * @param buffer The buffer to read from, which must be at least size * sector_size in length nkeynes@1107: * @param mode The sector mode of the data in the buffer, which cannot be SECTOR_UNKNOWN nkeynes@1107: * @param size Number of sectors in the buffer nkeynes@1107: * @param freeOnDestroy If true, the source owns the buffer and will release it when the nkeynes@1107: * source is destroyed. nkeynes@1107: */ nkeynes@1107: sector_source_t mem_sector_source_new_buffer( unsigned char *buffer, sector_mode_t mode, cdrom_count_t size, nkeynes@1107: gboolean freeOnDestroy ); nkeynes@1107: nkeynes@1107: /** nkeynes@1107: * Retrieve the underlying buffer for a memory source nkeynes@1107: */ nkeynes@1107: unsigned char *mem_sector_source_get_buffer( sector_source_t source ); nkeynes@1107: nkeynes@1097: /** nkeynes@1097: * Increment the reference count for a block device. nkeynes@1097: */ nkeynes@1097: void sector_source_ref( sector_source_t device ); nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Unreference a block device. If decremented to 0, the device will be nkeynes@1097: * destroyed. nkeynes@1097: */ nkeynes@1097: void sector_source_unref( sector_source_t device ); nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Release an unbound block device. If the ref count is 0, the device is nkeynes@1097: * destroyed. Otherwise the function has no effect. nkeynes@1097: */ nkeynes@1097: void sector_source_release( sector_source_t device ); nkeynes@1097: nkeynes@1097: cdrom_error_t sector_source_read( sector_source_t device, cdrom_lba_t lba, cdrom_count_t block_count, unsigned char *buf ); nkeynes@1097: nkeynes@1097: cdrom_error_t sector_source_read_sectors( sector_source_t device, cdrom_lba_t lba, cdrom_count_t block_count, nkeynes@1097: cdrom_read_mode_t mode, unsigned char *buf, size_t *length ); nkeynes@1097: nkeynes@1097: /***** Internals for sector source implementations *****/ nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Initialize a new (pre-allocated) sector source nkeynes@1097: */ nkeynes@1097: sector_source_t sector_source_init( sector_source_t device, sector_source_type_t type, sector_mode_t mode, cdrom_count_t size, nkeynes@1097: sector_source_read_fn_t readfn, sector_source_destroy_fn_t destroyfn ); nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Default sector source destructor method nkeynes@1097: */ nkeynes@1097: void default_sector_source_destroy( sector_source_t device ); nkeynes@1097: nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Extract the necessary fields from a single raw sector for the given read mode. nkeynes@1097: * @param raw_sector input raw 2352 byte sector nkeynes@1097: * @param mode sector mode and field specification flags nkeynes@1097: * @param buf output buffer for sector data nkeynes@1097: * @param length output length of sector written to buf nkeynes@1097: * @return CDROM_ERROR_OK on success, otherwise an appropriate error code. nkeynes@1097: */ nkeynes@1097: cdrom_error_t sector_extract_from_raw( unsigned char *raw_sector, cdrom_read_mode_t mode, unsigned char *buf, size_t *length ); nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Test if the given pointer is a valid sector source nkeynes@1097: */ nkeynes@1097: #define IS_SECTOR_SOURCE(dev) ((dev) != NULL && ((sector_source_t)(dev))->tag == SECTOR_SOURCE_TAG) nkeynes@1097: nkeynes@1097: /** nkeynes@1097: * Test if the given pointer is a valid sector source of the given type nkeynes@1097: */ nkeynes@1097: #define IS_SECTOR_SOURCE_TYPE(dev,id) (IS_SECTOR_SOURCE(dev) && ((sector_source_t)(dev))->type == id) nkeynes@1097: nkeynes@1097: nkeynes@1097: nkeynes@1097: #ifdef __cplusplus nkeynes@1097: } nkeynes@1097: #endif nkeynes@1097: nkeynes@1097: #endif /* !cdrom_sector_H */