Ticket #3473: mixed-mode-cd.patch

File mixed-mode-cd.patch, 17.2 KB (added by Ziusudra, 14 years ago)
  • src/add-ons/kernel/partitioning_systems/session/Disc.h

     
    4545    static  const int       kBlockSize = 2048;
    4646
    4747private:
     48            uint32          _CheckForYellowBook(
     49                                cdrom_full_table_of_contents_entry entries[],
     50                                uint32 count);
    4851            status_t        _ParseTableOfContents(
    4952                                cdrom_full_table_of_contents_entry entries[],
    5053                                uint32 count);
  • src/add-ons/kernel/partitioning_systems/session/Disc.cpp

     
    66 *      Tyler Akidau, haiku@akidau.net
    77 */
    88
    9 
    109/*! \file Disc.cpp
    1110
    1211    Disc class implementation, used to enumerate the CD/DVD sessions.
     
    2120    number \c 0x2.
    2221*/
    2322
    24 
    2523#include "Disc.h"
    2624
    2725#include <DiskDeviceDefs.h>
     
    8684
    8785    off_t   start_lba;
    8886    uint8   control;
    89         //!< only used to give what are probably useless warnings
     87        // Used to check for Yellow/Red Book mixed-mode CDs.
    9088    uint8   adr;
    9189        //!< only used to give what are probably useless warnings
    9290};
     
    554552        count = (header->length - 2)
    555553            / sizeof(cdrom_full_table_of_contents_entry);
    556554
     555        count = _CheckForYellowBook(entries, count);
    557556        error = _ParseTableOfContents(entries, count);
    558557//      Dump();
    559558        if (!error) {
     
    696695}
    697696
    698697
     698/*! \brief Checks for Yellow Book data tracks in audio sessions and if found
     699    inserts them as a new data session.
     700*/
     701uint32
     702Disc::_CheckForYellowBook(cdrom_full_table_of_contents_entry entries[],
     703    uint32 count)
     704{
     705    uint8 foundCount = 0;
     706    uint8 endLBAEntry = 0;
     707    uint8 trackTwo = 0;
     708
     709    // Make sure TOC has only one session and that it is audio.
     710    bool sessionIsAudio = true;
     711    for (uint32 i = 0; i < count; i++) {
     712        if (entries[i].point == 0xA2) {
     713            if (entries[i].control & kControlDataTrack) {
     714                sessionIsAudio = false;
     715                break;
     716            }
     717            foundCount++;
     718            endLBAEntry = i;
     719        }
     720    }
     721    if ((sessionIsAudio == false) || (foundCount != 1))
     722        return count;
     723
     724    TRACE(("%s: Single audio session, checking for data track\n",
     725        kModuleDebugName));
     726
     727    // See if there are any data tracks.
     728    for (uint32 i = 0; i < count; i++) {
     729        if (0 < entries[i].point && entries[i].point < 100
     730                && (entries[i].control & kControlDataTrack)) {
     731            if (entries[i].point == 1) {
     732                // Create a new endLBA point for session one.
     733                entries[count] = entries[endLBAEntry];
     734                entries[count].control = entries[i].control;
     735
     736                // Get track two and use it's start as
     737                // the end of our new session.
     738                for (uint8 j = 0; j < count; j++) {
     739                    if (entries[j].point == 2) {
     740                        trackTwo = j;
     741                        break;
     742                    }
     743                }
     744                entries[count].pminutes = entries[trackTwo].pminutes;
     745                entries[count].pseconds = entries[trackTwo].pseconds;
     746                entries[count].pframes = entries[trackTwo].pframes;
     747
     748                // Change the other points to session two.
     749                for (uint32 j = 0; j < count; j++) {
     750                    entries[j].session = 2;
     751                }
     752                entries[i].session = 1;
     753
     754                count++;
     755                TRACE(("%s: first track is data, adjusted TOC\n",
     756                    kModuleDebugName));
     757                break;
     758            } else {
     759                // Change the track to session two.
     760                entries[i].session = 2;
     761
     762                // Create a new endLBA point for session two.
     763                entries[count] = entries[endLBAEntry];
     764                entries[count].session = 2;
     765                entries[count].control = entries[i].control;
     766
     767                // Use the beginning of the data track as the
     768                // end of the previous session.
     769                entries[endLBAEntry].pminutes = entries[i].pminutes;
     770                entries[endLBAEntry].pseconds = entries[i].pseconds;
     771                entries[endLBAEntry].pframes = entries[i].pframes;
     772
     773                count++;
     774                TRACE(("%s: last track is data, adjusted TOC\n",
     775                    kModuleDebugName));
     776                break;
     777            }
     778        }
     779    }
     780    return count;
     781}
     782
     783
    699784/*! \brief Reads through the given table of contents data and creates an
    700785    unsorted, unverified (i.e. non-error-checked) list of sessions and tracks.
    701786*/
     
    813898                    session->track_list.Add(track);
    814899                } else {
    815900                    WARN(("%s: warning: illegal point 0x%2x found in table of "
    816                         "contents\n", kModuleDebugName, entries[i].point));
     901                        "contents\n", kModuleDebugName, point));
    817902                }
    818903                break;
    819904        }
  • src/add-ons/kernel/partitioning_systems/session/session.cpp

     
    1818#include "Debug.h"
    1919#include "Disc.h"
    2020
    21 
    2221#define SESSION_PARTITION_MODULE_NAME "partitioning_systems/session/v1"
    2322
    2423
     
    4645    device_geometry geometry;
    4746    float result = -1;
    4847    if (partition->flags & B_PARTITION_IS_DEVICE
    49         && partition->block_size == 2048
    50         && ioctl(fd, B_GET_GEOMETRY, &geometry) == 0
    51         && geometry.device_type == B_CD) {
     48            && partition->block_size == 2048
     49            && ioctl(fd, B_GET_GEOMETRY, &geometry) == 0
     50            && geometry.device_type == B_CD) {
    5251        Disc *disc = new Disc(fd);
    5352        if (disc && disc->InitCheck() == B_OK) {
    5453            *cookie = static_cast<void*>(disc);
    55             result = 0.7;
     54            // If we have more than one session then we override the
     55            // filesystem drivers. GetSession is 0 indexed.
     56            if (disc->GetSession(1))
     57                result = 0.9;
     58            else
     59                result = 0.1;
    5660        } else
    5761            delete disc;
    5862    }
  • src/add-ons/kernel/file_systems/cdda/kernel_interface.cpp

     
    542542uint32
    543543count_audio_tracks(scsi_toc_toc* toc)
    544544{
    545     uint32 lastTrack = toc->last_track + 1 - toc->first_track;
     545    uint32 trackCount = toc->last_track + 1 - toc->first_track;
    546546    uint32 count = 0;
    547     for (uint32 i = 0; i < lastTrack; i++) {
     547    for (uint32 i = 0; i < trackCount; i++) {
    548548        if (!is_data_track(toc->tracks[i]))
    549549            count++;
    550550    }
     
    747747
    748748        snprintf(title, sizeof(title), "%02lu:%02lu",
    749749            uint32(inode->FrameCount() / kFramesPerMinute),
    750             uint32((inode->FrameCount() % kFramesPerMinute) / kFramesPerSecond));
     750            uint32((inode->FrameCount() % kFramesPerMinute)
     751                / kFramesPerSecond));
    751752        inode->AddAttribute("Audio:Length", B_STRING_TYPE, title);
    752753        inode->AddAttribute("BEOS:TYPE", B_MIME_STRING_TYPE, "audio/x-wav");
    753754    }
     
    13221323            while (i.HasNext()) {
    13231324                attr_cookie* cookie = i.Next();
    13241325                if (cookie->current == attribute)
    1325                     cookie->current = attribute->GetDoublyLinkedListLink()->next;
     1326                    cookie->current
     1327                        = attribute->GetDoublyLinkedListLink()->next;
    13261328            }
    13271329
    13281330            iterator.Remove();
     
    13691371
    13701372    status_t status = read_table_of_contents(fd, toc, 2048);
    13711373
    1372     // there has to be at least a single audio track
    1373     if (status == B_OK && count_audio_tracks(toc) == 0)
    1374         status = B_BAD_TYPE;
     1374    // If we succeeded in reading the toc, check the tracks in the
     1375    // partition, which may not be the whole CD, and if any are audio,
     1376    // claim the partition.
     1377    if (status == B_OK) {
     1378        uint32 trackCount = toc->last_track + (uint32)1 - toc->first_track;
     1379        off_t sessionStartLBA = partition->offset / partition->block_size;
     1380        off_t sessionEndLBA = sessionStartLBA
     1381            + (partition->size / partition->block_size);
     1382        TRACE(("cdda_identify_partition: session at %lld-%lld\n",
     1383            sessionStartLBA, sessionEndLBA));
     1384        status = B_ENTRY_NOT_FOUND;
     1385        for (uint32 i = 0; i < trackCount; i++) {
     1386            // We have to get trackLBA from track.start.time since
     1387            // track.start.lba is useless for this.
     1388            // This is how session gets it.
     1389            off_t trackLBA
     1390                = ((toc->tracks[i].start.time.minute * kFramesPerMinute)
     1391                + (toc->tracks[i].start.time.second * kFramesPerSecond)
     1392                + toc->tracks[i].start.time.frame - 150);
     1393            if ((trackLBA >= sessionStartLBA) && (trackLBA < sessionEndLBA)) {
     1394                if (is_data_track(toc->tracks[i])) {
     1395                    TRACE(("cdda_identify_partition: track %ld at %lld is "
     1396                        "data\n", i + 1, trackLBA));
     1397                    status = B_BAD_TYPE;
     1398                } else {
     1399                    TRACE(("cdda_identify_partition: track %ld at %lld is "
     1400                        "audio\n", i + 1, trackLBA));
     1401                    status = B_OK;
     1402                    break;
     1403                }
     1404            }
     1405        }
     1406    }
    13751407
    13761408    if (status < B_OK) {
    13771409        free(toc);
     
    13791411    }
    13801412
    13811413    *_cookie = toc;
    1382     return 0.8f;
     1414    return 0.8;
    13831415}
    13841416
    13851417
     
    16541686    }
    16551687
    16561688    if (cookie->buffer == NULL) {
    1657         // TODO: move that to open() to make sure reading can't fail for this reason?
     1689        // TODO: move to open() to insure reading can't fail for this reason?
    16581690        cookie->buffer = malloc(volume->BufferSize());
    16591691        if (cookie->buffer == NULL)
    16601692            return B_NO_MEMORY;
     
    17311763    Volume* volume = (Volume*)_volume->private_volume;
    17321764    Inode* inode = (Inode*)_node->private_node;
    17331765
    1734     TRACE(("cdda_read_stat: vnode %p (0x%Lx), stat %p\n", inode, inode->ID(), stat));
     1766    TRACE(("cdda_read_stat: vnode %p (0x%Lx), stat %p\n", inode, inode->ID(),
     1767        stat));
    17351768
    17361769    fill_stat_buffer(volume, inode, NULL, *stat);
    17371770
     
    18101843    Volume* volume = (Volume*)_volume->private_volume;
    18111844    Inode* inode = (Inode*)_node->private_node;
    18121845
    1813     TRACE(("cdda_read_dir: vnode %p, cookie %p, buffer = %p, bufferSize = %ld, num = %p\n", _node, _cookie, dirent, bufferSize,_num));
     1846    TRACE(("cdda_read_dir: vnode %p, cookie %p, buffer = %p, bufferSize = %ld,"
     1847        " num = %p\n", _node, _cookie, buffer, bufferSize,_num));
    18141848
    18151849    if ((Inode*)_node->private_node != &volume->RootNode())
    18161850        return B_BAD_VALUE;
     
    19061940{
    19071941    dir_cookie* cookie = (dir_cookie*)_cookie;
    19081942
    1909     TRACE(("cdda_freecookie: entry vnode %p, cookie %p\n", _vnode, cookie));
     1943    TRACE(("cdda_freecookie: entry vnode %p, cookie %p\n", _node, cookie));
    19101944
    19111945    free(cookie);
    19121946    return 0;
  • src/add-ons/kernel/file_systems/cdda/cddb.cpp

     
    2525
    2626
    2727/*!
    28     Computes the CD Disc ID as specified in the FreeDB how-to (code taken from there).
     28    Computes the CD Disc ID as specified in the FreeDB how-to (code taken from
     29    there).
    2930*/
    3031uint32
    3132compute_cddb_disc_id(scsi_toc_toc &toc)
    3233{
    33     int32 numTracks = toc.last_track + 1 - toc.first_track;
     34    int32 trackCount = toc.last_track + 1 - toc.first_track;
    3435    uint32 n = 0;
    3536
    36     for (int32 i = 0; i < numTracks; i++) {
     37    for (int32 i = 0; i < trackCount; i++) {
    3738        n = n + cddb_sum((toc.tracks[i].start.time.minute * 60)
    3839            + toc.tracks[i].start.time.second);
    3940    }
    4041
    41     int32 t = ((toc.tracks[numTracks].start.time.minute * 60)
    42             + toc.tracks[numTracks].start.time.second)
     42    int32 t = ((toc.tracks[trackCount].start.time.minute * 60)
     43            + toc.tracks[trackCount].start.time.second)
    4344        - ((toc.tracks[0].start.time.minute * 60)
    4445            + toc.tracks[0].start.time.second);
    4546
    46     return (n % 0xff) << 24 | t << 8 | numTracks;
     47    return (n % 0xff) << 24 | t << 8 | trackCount;
    4748}
  • src/add-ons/kernel/partitioning_systems/session/Debug.cpp

     
    11//----------------------------------------------------------------------
    2 //  This software is part of the OpenBeOS distribution and is covered 
     2//  This software is part of the OpenBeOS distribution and is covered
    33//  by the OpenBeOS license.
    44//
    55//  This version copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
     
    2525    \brief Increases the indentation level, prints out the enclosing function's
    2626    name, and creates a \c DebugHelper object on the stack to automatically
    2727    decrease the indentation level upon function exit.
    28    
     28
    2929    This macro should be called at the very beginning of any function in
    3030    which you wish to use any of the other debugging macros.
    31    
     31
    3232    If DEBUG is undefined, does nothing.
    3333*/
    3434//----------------------------------------------------------------------
    3535/*! \def PRINT(x)
    3636    \brief Prints out the enclosing function's name followed by the contents
    3737    of \a x at the current indentation level.
    38    
     38
    3939    \param x A printf-style format string enclosed in an extra set of parenteses,
    4040             e.g. PRINT(("%d\n", 0));
    41    
     41
    4242    If DEBUG is undefined, does nothing.
    4343*/
    4444//----------------------------------------------------------------------
    4545/*! \def LPRINT(x)
    4646    \brief Identical to \c PRINT(x), except that the line number in the source
    4747    file at which the macro is invoked is also printed.
    48    
     48
    4949    \param x A printf-style format string enclosed in an extra set of parenteses,
    5050             e.g. PRINT(("%d\n", 0));
    51    
     51
    5252    If DEBUG is undefined, does nothing.
    5353*/
    5454//----------------------------------------------------------------------
     
    6060             e.g. PRINT(("%d\n", 0));
    6161
    6262    If DEBUG is undefined, does nothing.
    63 */           
     63*/
    6464//----------------------------------------------------------------------
    6565/*! \def PRINT_INDENT()
    6666    \brief Prints out enough indentation characters to indent the current line
    6767    to the current indentation level (assuming the cursor was flush left to
    6868    begin with...).
    69    
     69
    7070    This function is called by the other \c *PRINT* macros, and isn't really
    7171    intended for general consumption, but you might find it useful.
    72    
     72
    7373    If DEBUG is undefined, does nothing.
    7474*/
    7575//----------------------------------------------------------------------
     
    7777    \brief Calls \c LPRINT(x) with a format string listing the error
    7878    code in \c error (assumed to be a \c status_t value) and the
    7979    corresponding text error code returned by a call to \c strerror().
    80    
     80
    8181    This function is called by the \c RETURN* macros, and isn't really
    8282    intended for general consumption, but you might find it useful.
    83    
     83
    8484    \param error A \c status_t error code to report.
    85    
     85
    8686    If DEBUG is undefined, does nothing.
    8787*/
    8888//----------------------------------------------------------------------
     
    9090    \brief Calls \c REPORT_ERROR(error) if error is a an error code (i.e.
    9191    negative), otherwise remains silent. In either case, the enclosing
    9292    function is then exited with a call to \c "return error;".
    93        
     93
    9494    \param error A \c status_t error code to report (if negative) and return.
    95    
     95
    9696    If DEBUG is undefined, silently returns the value in \c error.
    9797*/
    9898//----------------------------------------------------------------------
     
    100100    \brief Prints out a description of the error code being returned
    101101    (which, in this case, may be either "erroneous" or "successful")
    102102    and then exits the enclosing function with a call to \c "return error;".
    103        
     103
    104104    \param error A \c status_t error code to report and return.
    105    
     105
    106106    If DEBUG is undefined, silently returns the value in \c error.
    107107*/
    108108//----------------------------------------------------------------------
    109109/*! \def FATAL(x)
    110110    \brief Prints out a fatal error message.
    111    
     111
    112112    This one's still a work in progress...
    113113
    114114    \param x A printf-style format string enclosed in an extra set of parenteses,
    115115             e.g. PRINT(("%d\n", 0));
    116    
     116
    117117    If DEBUG is undefined, does nothing.
    118118*/
    119119//----------------------------------------------------------------------
     
    133133    \brief If debug is defined, \a x is passed along to the code and
    134134    executed unmodified. If \c DEBUG is undefined, the contents of
    135135    \a x disappear into the ether.
    136    
     136
    137137    \param x Damn near anything resembling valid C\C++.
    138138*/
    139139//----------------------------------------------------------------------
     
    143143    enclosed printf-style format string found in \a x.
    144144
    145145    \param x A printf-style format string enclosed in an extra set of parenteses,
    146              e.g. PRINT(("%d\n", 0));   
     146             e.g. PRINT(("%d\n", 0));
    147147*/
    148148
    149149
     
    175175
    176176/*! \brief Returns the current debug indentation level for the
    177177    current thread.
    178    
     178
    179179    NOTE: indentation is currently unsupported for R5::kernelland due
    180180    to lack of thread local storage support.
    181181*/
     
    188188    return 1;
    189189#endif
    190190}
    191    
     191
    192192//----------------------------------------------------------------------
    193193// static functions
    194194//----------------------------------------------------------------------
     
    227227    if (!tls_handle_initialized) {
    228228        if (atomic_or(&tls_spinlock, 1) == 0) {
    229229            // First one in gets to init
    230             tls_handle = tls_allocate();   
     230            tls_handle = tls_allocate();
    231231            tls_handle_initialized = true;
    232232            atomic_and(&tls_spinlock, 0);
    233233        } else {
     
    243243
    244244/*! \brief Helper class for initializing the debugging output
    245245    file.
    246    
     246
    247247    Note that this hummer isn't threadsafe, but it doesn't really
    248248    matter for our concerns, since the worst it'll result in is
    249249    a dangling file descriptor, and that would be in the case of
     
    252252*/
    253253class DebugOutputFile {
    254254public:
    255     DebugOutputFile(const char *filename = NULL) 
     255    DebugOutputFile(const char *filename = NULL)
    256256        : fFile(-1)
    257257    {
    258258        Init(filename);
    259259    }
    260    
     260
    261261    ~DebugOutputFile() {
    262262        if (fFile >= 0)
    263263            close(fFile);
    264264    }
    265    
     265
    266266    void Init(const char *filename) {
    267267        if (fFile < 0 && filename)
    268268            fFile = open(filename, O_RDWR | O_CREAT | O_TRUNC);
    269269    }
    270    
     270
    271271    int File() const { return fFile; }
    272272private:
    273273    int fFile;