Ticket #3473: mixed-mode-cd.patch
File mixed-mode-cd.patch, 17.2 KB (added by , 14 years ago) |
---|
-
src/add-ons/kernel/partitioning_systems/session/Disc.h
45 45 static const int kBlockSize = 2048; 46 46 47 47 private: 48 uint32 _CheckForYellowBook( 49 cdrom_full_table_of_contents_entry entries[], 50 uint32 count); 48 51 status_t _ParseTableOfContents( 49 52 cdrom_full_table_of_contents_entry entries[], 50 53 uint32 count); -
src/add-ons/kernel/partitioning_systems/session/Disc.cpp
6 6 * Tyler Akidau, haiku@akidau.net 7 7 */ 8 8 9 10 9 /*! \file Disc.cpp 11 10 12 11 Disc class implementation, used to enumerate the CD/DVD sessions. … … 21 20 number \c 0x2. 22 21 */ 23 22 24 25 23 #include "Disc.h" 26 24 27 25 #include <DiskDeviceDefs.h> … … 86 84 87 85 off_t start_lba; 88 86 uint8 control; 89 // !< only used to give what are probably useless warnings87 // Used to check for Yellow/Red Book mixed-mode CDs. 90 88 uint8 adr; 91 89 //!< only used to give what are probably useless warnings 92 90 }; … … 554 552 count = (header->length - 2) 555 553 / sizeof(cdrom_full_table_of_contents_entry); 556 554 555 count = _CheckForYellowBook(entries, count); 557 556 error = _ParseTableOfContents(entries, count); 558 557 // Dump(); 559 558 if (!error) { … … 696 695 } 697 696 698 697 698 /*! \brief Checks for Yellow Book data tracks in audio sessions and if found 699 inserts them as a new data session. 700 */ 701 uint32 702 Disc::_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 699 784 /*! \brief Reads through the given table of contents data and creates an 700 785 unsorted, unverified (i.e. non-error-checked) list of sessions and tracks. 701 786 */ … … 813 898 session->track_list.Add(track); 814 899 } else { 815 900 WARN(("%s: warning: illegal point 0x%2x found in table of " 816 "contents\n", kModuleDebugName, entries[i].point));901 "contents\n", kModuleDebugName, point)); 817 902 } 818 903 break; 819 904 } -
src/add-ons/kernel/partitioning_systems/session/session.cpp
18 18 #include "Debug.h" 19 19 #include "Disc.h" 20 20 21 22 21 #define SESSION_PARTITION_MODULE_NAME "partitioning_systems/session/v1" 23 22 24 23 … … 46 45 device_geometry geometry; 47 46 float result = -1; 48 47 if (partition->flags & B_PARTITION_IS_DEVICE 49 && partition->block_size == 204850 && ioctl(fd, B_GET_GEOMETRY, &geometry) == 051 && geometry.device_type == B_CD) {48 && partition->block_size == 2048 49 && ioctl(fd, B_GET_GEOMETRY, &geometry) == 0 50 && geometry.device_type == B_CD) { 52 51 Disc *disc = new Disc(fd); 53 52 if (disc && disc->InitCheck() == B_OK) { 54 53 *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; 56 60 } else 57 61 delete disc; 58 62 } -
src/add-ons/kernel/file_systems/cdda/kernel_interface.cpp
542 542 uint32 543 543 count_audio_tracks(scsi_toc_toc* toc) 544 544 { 545 uint32 lastTrack= toc->last_track + 1 - toc->first_track;545 uint32 trackCount = toc->last_track + 1 - toc->first_track; 546 546 uint32 count = 0; 547 for (uint32 i = 0; i < lastTrack; i++) {547 for (uint32 i = 0; i < trackCount; i++) { 548 548 if (!is_data_track(toc->tracks[i])) 549 549 count++; 550 550 } … … 747 747 748 748 snprintf(title, sizeof(title), "%02lu:%02lu", 749 749 uint32(inode->FrameCount() / kFramesPerMinute), 750 uint32((inode->FrameCount() % kFramesPerMinute) / kFramesPerSecond)); 750 uint32((inode->FrameCount() % kFramesPerMinute) 751 / kFramesPerSecond)); 751 752 inode->AddAttribute("Audio:Length", B_STRING_TYPE, title); 752 753 inode->AddAttribute("BEOS:TYPE", B_MIME_STRING_TYPE, "audio/x-wav"); 753 754 } … … 1322 1323 while (i.HasNext()) { 1323 1324 attr_cookie* cookie = i.Next(); 1324 1325 if (cookie->current == attribute) 1325 cookie->current = attribute->GetDoublyLinkedListLink()->next; 1326 cookie->current 1327 = attribute->GetDoublyLinkedListLink()->next; 1326 1328 } 1327 1329 1328 1330 iterator.Remove(); … … 1369 1371 1370 1372 status_t status = read_table_of_contents(fd, toc, 2048); 1371 1373 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 } 1375 1407 1376 1408 if (status < B_OK) { 1377 1409 free(toc); … … 1379 1411 } 1380 1412 1381 1413 *_cookie = toc; 1382 return 0.8 f;1414 return 0.8; 1383 1415 } 1384 1416 1385 1417 … … 1654 1686 } 1655 1687 1656 1688 if (cookie->buffer == NULL) { 1657 // TODO: move t hat to open() to makesure reading can't fail for this reason?1689 // TODO: move to open() to insure reading can't fail for this reason? 1658 1690 cookie->buffer = malloc(volume->BufferSize()); 1659 1691 if (cookie->buffer == NULL) 1660 1692 return B_NO_MEMORY; … … 1731 1763 Volume* volume = (Volume*)_volume->private_volume; 1732 1764 Inode* inode = (Inode*)_node->private_node; 1733 1765 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)); 1735 1768 1736 1769 fill_stat_buffer(volume, inode, NULL, *stat); 1737 1770 … … 1810 1843 Volume* volume = (Volume*)_volume->private_volume; 1811 1844 Inode* inode = (Inode*)_node->private_node; 1812 1845 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)); 1814 1848 1815 1849 if ((Inode*)_node->private_node != &volume->RootNode()) 1816 1850 return B_BAD_VALUE; … … 1906 1940 { 1907 1941 dir_cookie* cookie = (dir_cookie*)_cookie; 1908 1942 1909 TRACE(("cdda_freecookie: entry vnode %p, cookie %p\n", _ vnode, cookie));1943 TRACE(("cdda_freecookie: entry vnode %p, cookie %p\n", _node, cookie)); 1910 1944 1911 1945 free(cookie); 1912 1946 return 0; -
src/add-ons/kernel/file_systems/cdda/cddb.cpp
25 25 26 26 27 27 /*! 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). 29 30 */ 30 31 uint32 31 32 compute_cddb_disc_id(scsi_toc_toc &toc) 32 33 { 33 int32 numTracks= toc.last_track + 1 - toc.first_track;34 int32 trackCount = toc.last_track + 1 - toc.first_track; 34 35 uint32 n = 0; 35 36 36 for (int32 i = 0; i < numTracks; i++) {37 for (int32 i = 0; i < trackCount; i++) { 37 38 n = n + cddb_sum((toc.tracks[i].start.time.minute * 60) 38 39 + toc.tracks[i].start.time.second); 39 40 } 40 41 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) 43 44 - ((toc.tracks[0].start.time.minute * 60) 44 45 + toc.tracks[0].start.time.second); 45 46 46 return (n % 0xff) << 24 | t << 8 | numTracks;47 return (n % 0xff) << 24 | t << 8 | trackCount; 47 48 } -
src/add-ons/kernel/partitioning_systems/session/Debug.cpp
1 1 //---------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 2 // This software is part of the OpenBeOS distribution and is covered 3 3 // by the OpenBeOS license. 4 4 // 5 5 // This version copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net … … 25 25 \brief Increases the indentation level, prints out the enclosing function's 26 26 name, and creates a \c DebugHelper object on the stack to automatically 27 27 decrease the indentation level upon function exit. 28 28 29 29 This macro should be called at the very beginning of any function in 30 30 which you wish to use any of the other debugging macros. 31 31 32 32 If DEBUG is undefined, does nothing. 33 33 */ 34 34 //---------------------------------------------------------------------- 35 35 /*! \def PRINT(x) 36 36 \brief Prints out the enclosing function's name followed by the contents 37 37 of \a x at the current indentation level. 38 38 39 39 \param x A printf-style format string enclosed in an extra set of parenteses, 40 40 e.g. PRINT(("%d\n", 0)); 41 41 42 42 If DEBUG is undefined, does nothing. 43 43 */ 44 44 //---------------------------------------------------------------------- 45 45 /*! \def LPRINT(x) 46 46 \brief Identical to \c PRINT(x), except that the line number in the source 47 47 file at which the macro is invoked is also printed. 48 48 49 49 \param x A printf-style format string enclosed in an extra set of parenteses, 50 50 e.g. PRINT(("%d\n", 0)); 51 51 52 52 If DEBUG is undefined, does nothing. 53 53 */ 54 54 //---------------------------------------------------------------------- … … 60 60 e.g. PRINT(("%d\n", 0)); 61 61 62 62 If DEBUG is undefined, does nothing. 63 */ 63 */ 64 64 //---------------------------------------------------------------------- 65 65 /*! \def PRINT_INDENT() 66 66 \brief Prints out enough indentation characters to indent the current line 67 67 to the current indentation level (assuming the cursor was flush left to 68 68 begin with...). 69 69 70 70 This function is called by the other \c *PRINT* macros, and isn't really 71 71 intended for general consumption, but you might find it useful. 72 72 73 73 If DEBUG is undefined, does nothing. 74 74 */ 75 75 //---------------------------------------------------------------------- … … 77 77 \brief Calls \c LPRINT(x) with a format string listing the error 78 78 code in \c error (assumed to be a \c status_t value) and the 79 79 corresponding text error code returned by a call to \c strerror(). 80 80 81 81 This function is called by the \c RETURN* macros, and isn't really 82 82 intended for general consumption, but you might find it useful. 83 83 84 84 \param error A \c status_t error code to report. 85 85 86 86 If DEBUG is undefined, does nothing. 87 87 */ 88 88 //---------------------------------------------------------------------- … … 90 90 \brief Calls \c REPORT_ERROR(error) if error is a an error code (i.e. 91 91 negative), otherwise remains silent. In either case, the enclosing 92 92 function is then exited with a call to \c "return error;". 93 93 94 94 \param error A \c status_t error code to report (if negative) and return. 95 95 96 96 If DEBUG is undefined, silently returns the value in \c error. 97 97 */ 98 98 //---------------------------------------------------------------------- … … 100 100 \brief Prints out a description of the error code being returned 101 101 (which, in this case, may be either "erroneous" or "successful") 102 102 and then exits the enclosing function with a call to \c "return error;". 103 103 104 104 \param error A \c status_t error code to report and return. 105 105 106 106 If DEBUG is undefined, silently returns the value in \c error. 107 107 */ 108 108 //---------------------------------------------------------------------- 109 109 /*! \def FATAL(x) 110 110 \brief Prints out a fatal error message. 111 111 112 112 This one's still a work in progress... 113 113 114 114 \param x A printf-style format string enclosed in an extra set of parenteses, 115 115 e.g. PRINT(("%d\n", 0)); 116 116 117 117 If DEBUG is undefined, does nothing. 118 118 */ 119 119 //---------------------------------------------------------------------- … … 133 133 \brief If debug is defined, \a x is passed along to the code and 134 134 executed unmodified. If \c DEBUG is undefined, the contents of 135 135 \a x disappear into the ether. 136 136 137 137 \param x Damn near anything resembling valid C\C++. 138 138 */ 139 139 //---------------------------------------------------------------------- … … 143 143 enclosed printf-style format string found in \a x. 144 144 145 145 \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)); 147 147 */ 148 148 149 149 … … 175 175 176 176 /*! \brief Returns the current debug indentation level for the 177 177 current thread. 178 178 179 179 NOTE: indentation is currently unsupported for R5::kernelland due 180 180 to lack of thread local storage support. 181 181 */ … … 188 188 return 1; 189 189 #endif 190 190 } 191 191 192 192 //---------------------------------------------------------------------- 193 193 // static functions 194 194 //---------------------------------------------------------------------- … … 227 227 if (!tls_handle_initialized) { 228 228 if (atomic_or(&tls_spinlock, 1) == 0) { 229 229 // First one in gets to init 230 tls_handle = tls_allocate(); 230 tls_handle = tls_allocate(); 231 231 tls_handle_initialized = true; 232 232 atomic_and(&tls_spinlock, 0); 233 233 } else { … … 243 243 244 244 /*! \brief Helper class for initializing the debugging output 245 245 file. 246 246 247 247 Note that this hummer isn't threadsafe, but it doesn't really 248 248 matter for our concerns, since the worst it'll result in is 249 249 a dangling file descriptor, and that would be in the case of … … 252 252 */ 253 253 class DebugOutputFile { 254 254 public: 255 DebugOutputFile(const char *filename = NULL) 255 DebugOutputFile(const char *filename = NULL) 256 256 : fFile(-1) 257 257 { 258 258 Init(filename); 259 259 } 260 260 261 261 ~DebugOutputFile() { 262 262 if (fFile >= 0) 263 263 close(fFile); 264 264 } 265 265 266 266 void Init(const char *filename) { 267 267 if (fFile < 0 && filename) 268 268 fFile = open(filename, O_RDWR | O_CREAT | O_TRUNC); 269 269 } 270 270 271 271 int File() const { return fFile; } 272 272 private: 273 273 int fFile;