Exemple #1
0
// plays cdda audio
// sector:
//  byte 0 - minute
//  byte 1 - second
//  byte 2 - frame
// does NOT uses bcd format
long CDRplay(unsigned char *sector) {
	long ret;

	if (!IsCdHandleOpen())
		return 0;

	// If play was called with the same time as the previous call,
	// don't restart it. Of course, if play is called with a different
	// track, stop playing the current stream.
	if (playing) {
		if (msf_to_lba(sector[0], sector[1], sector[2]) == initial_time)
			return 0;
		else
			CDRstop();
	}

	initial_time = msf_to_lba(sector[0], sector[1], sector[2]);

	if (ReadMode == THREADED) pthread_mutex_lock(&mut);
	ret = PlayCDDA(sector);
	if (ReadMode == THREADED) pthread_mutex_unlock(&mut);

	if (ret == 0) {
		playing = 1;
		return 0;
	}

	return -1;
}
Exemple #2
0
void *CdrThread(void *arg) {
	unsigned char curTime[3];
	int i;

	for (;;) {
		pthread_mutex_lock(&mut);
		locked = 1;

		pthread_cond_wait(&cond, &mut);

		if (stopth == 2) pthread_exit(NULL);
		// refill the buffer
		cacheaddr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0);

		memcpy(curTime, &cr.msf, 3);

		PRINTF("start thc %d:%d:%d\n", curTime[0], curTime[1], curTime[2]);

		for (i = 0; i < CacheSize; i++) {
			cdcache[i].cr.msf.cdmsf_min0 = curTime[0];
			cdcache[i].cr.msf.cdmsf_sec0 = curTime[1];
			cdcache[i].cr.msf.cdmsf_frame0 = curTime[2];

			PRINTF("reading %d:%d:%d\n", curTime[0], curTime[1], curTime[2]);

			cdcache[i].ret = ReadSector((crdata *)&cdcache[i].cr);
			if (cdcache[i].ret == -1) break;

			PRINTF("readed %x:%x:%x\n", cdcache[i].cr.buf[12], cdcache[i].cr.buf[13], cdcache[i].cr.buf[14]);

			cdcache[i].msf[0] = curTime[0];
			cdcache[i].msf[1] = curTime[1];
			cdcache[i].msf[2] = curTime[2];

			curTime[2]++;
			if (curTime[2] == 75) {
				curTime[2] = 0;
				curTime[1]++;
				if (curTime[1] == 60) {
					curTime[1] = 0;
					curTime[0]++;
				}
			}

			if (stopth) break;
		}

		pthread_mutex_unlock(&mut);
	}

	return NULL;
}
Exemple #3
0
static void
dump_full_table_of_contents(uchar* data, uint16 dataLength)
{
	cdrom_table_of_contents_header* header
		= (cdrom_table_of_contents_header*)data;
	cdrom_full_table_of_contents_entry* entries
		= (cdrom_full_table_of_contents_entry*)(data + 4);
	int headerLength = B_BENDIAN_TO_HOST_INT16(header->length);

	if (dataLength < headerLength) {
		TRACE(("dump_full_table_of_contents: warning, data buffer not large "
			"enough (%d < %d)\n", dataLength, headerLength));
		headerLength = dataLength;
	}

	TRACE(("%s: table of contents dump:\n", kModuleDebugName));
	TRACE(("--------------------------------------------------\n"));
	TRACE(("header:\n"));
	TRACE(("  length = %d\n", headerLength));
	TRACE(("  first  = %d\n", header->first));
	TRACE(("  last   = %d\n", header->last));

	int count = (headerLength - 2) / sizeof(cdrom_full_table_of_contents_entry);
	TRACE(("\n"));
	TRACE(("entry count = %d\n", count));

	for (int i = 0; i < count; i++) {
		TRACE(("\n"));
		TRACE(("entry #%d:\n", i));
		TRACE(("  session  = %d\n", entries[i].session));
		TRACE(("  adr      = %d\n", entries[i].adr));
		TRACE(("  control  = %d (%s track, copy %s)\n", entries[i].control,
			(entries[i].control & kControlDataTrack ? "data" : "audio"),
			(entries[i].control & kControlCopyPermitted
				? "permitted" : "prohibited")));
		TRACE(("  tno      = %d\n", entries[i].tno));
		TRACE(("  point    = %d (0x%.2x)\n", entries[i].point,
			entries[i].point));
		TRACE(("  minutes  = %d\n", entries[i].minutes));
		TRACE(("  frames   = %d\n", entries[i].seconds));
		TRACE(("  seconds  = %d\n", entries[i].frames));
		TRACE(("  zero     = %d\n", entries[i].zero));
		TRACE(("  pminutes = %d\n", entries[i].pminutes));
		TRACE(("  pseconds = %d\n", entries[i].pseconds));
		TRACE(("  pframes  = %d\n", entries[i].pframes));
		TRACE(("  lba      = %lld\n",
			msf_to_lba(make_msf_address(entries[i].pminutes,
			entries[i].pseconds, entries[i].pframes))));
	}
	TRACE(("--------------------------------------------------\n"));
}
Exemple #4
0
bool mcd_isa_device::read_sector(bool first)
{
	if((m_irq & IRQ_DATACOMP) && !first)
		m_isa->irq5_w(ASSERT_LINE);
	if(!m_readcount)
	{
		m_isa->drq5_w(CLEAR_LINE);
		m_data = false;
		return false;
	}
	uint32_t lba = msf_to_lba(m_readmsf);
	cdrom_read_data(m_cdrom_handle, lba - 150, m_buf, m_mode & 0x40 ? CD_TRACK_MODE1_RAW : CD_TRACK_MODE1);
	if(m_mode & 0x40)
	{
		//correct the header
		m_buf[12] = dec_2_bcd((m_readmsf >> 16) & 0xff);
		m_buf[13] = dec_2_bcd((m_readmsf >> 8) & 0xff);
	}
Exemple #5
0
// threaded reading (with cache)
long ReadThreaded() {
	int addr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0);
	int i;

	if (addr >= cacheaddr && addr < (cacheaddr + CacheSize) && cacheaddr != -1) {
		i = addr - cacheaddr;
		PRINTF("found %d\n", (addr - cacheaddr));
		cdbuffer = cdcache[i].cr.buf + 12;
		while (cdcache[i].msf[0] != cr.msf.cdmsf_min0 ||
			   cdcache[i].msf[1] != cr.msf.cdmsf_sec0 ||
			   cdcache[i].msf[2] != cr.msf.cdmsf_frame0) {
			if (locked == 1) {
				if (cdcache[i].ret == 0) break;
				return -1;
			}
			usleep(5000);
		}
		PRINTF("%d:%d:%d, %p, %p\n", cdcache[i].msf[0], cdcache[i].msf[1], cdcache[i].msf[2], cdbuffer, cdcache);
		found = 1;

		return 0;
	} else found = 0;

	if (locked == 0) {
		stopth = 1;
		while (locked == 0) { usleep(5000); }
		stopth = 0;
	}

	// not found in cache
	locked = 0;

	pthread_mutex_lock(&mut);
	pthread_cond_signal(&cond);
	pthread_mutex_unlock(&mut);

	return 0;
}
Exemple #6
0
/*! \brief Reads through the given table of contents data and creates an
	unsorted, unverified (i.e. non-error-checked) list of sessions and tracks.
*/
status_t
Disc::_ParseTableOfContents(cdrom_full_table_of_contents_entry entries[],
	uint32 count)
{
	DEBUG_INIT_ETC("Disc", ("entries: %p, count: %ld", entries, count));

	for (uint32 i = 0; i < count; i++) {
		// Find or create the appropriate session
		uint8 sessionIndex = entries[i].session;
		session* session = (struct session*)fSessionList->Find(sessionIndex);
		if (session == NULL) {
			session = new struct session(sessionIndex);
			if (session == NULL)
				return B_NO_MEMORY;

			fSessionList->Add(session);
		}

		uint8 point = entries[i].point;

		switch (point) {
			// first track hint
			case 0xA0:
				if (!session->first_track_hint_is_set()) {
					int8 firstTrackHint = entries[i].pminutes;
					if (1 <= firstTrackHint && firstTrackHint <= 99) {
						session->first_track_hint = firstTrackHint;
					} else {
						WARN(("%s: warning: illegal first track hint %d found "
							"for session %d\n", kModuleDebugName,
							firstTrackHint, sessionIndex));
					}
				} else {
					WARN(("%s: warning: duplicated first track hint values "
						"found for session %d; using first value "
						"encountered: %d", kModuleDebugName, sessionIndex,
						session->first_track_hint));
				}
				break;

			// last track hint
			case 0xA1:
				if (!session->last_track_hint_is_set()) {
					int8 lastTrackHint = entries[i].pminutes;
					if (1 <= lastTrackHint && lastTrackHint <= 99) {
						session->last_track_hint = lastTrackHint;
					} else {
						WARN(("%s: warning: illegal last track hint %d found "
							"for session %d\n", kModuleDebugName,
							lastTrackHint, sessionIndex));
					}
				} else {
					WARN(("%s: warning: duplicate last track hint values found "
						"for session %d; using first value encountered: %d",
						kModuleDebugName, sessionIndex,
						session->last_track_hint));
				}
				break;

			// end of session address
			case 0xA2:
				if (!session->end_lba_is_set()) {
					off_t endLBA = msf_to_lba(make_msf_address(
						entries[i].pminutes, entries[i].pseconds,
						entries[i].pframes));
					if (endLBA > 0) {
						session->end_lba = endLBA;
						// We also grab the session's control and adr values
						// from this entry
						session->control = entries[i].control;
						session->adr = entries[i].adr;
					} else {
						WARN(("%s: warning: illegal end lba %lld found for "
							"session %d\n", kModuleDebugName, endLBA,
							sessionIndex));
					}
				} else {
					WARN(("%s: warning: duplicate end lba values found for "
						"session %d; using first value encountered: %lld",
						kModuleDebugName, sessionIndex, session->end_lba));
				}
				break;

			// Valid, but uninteresting, points
			case 0xB0:
			case 0xB1:
			case 0xB2:
			case 0xB3:
			case 0xB4:
			case 0xC0:
			case 0xC1:
				break;

			default:
				// Anything else had better be a valid track number,
				// or it's an invalid point
				if (1 <= point && point <= 99) {
					// Create and add the track. We'll weed out any duplicates
					// later.
					uint8 trackIndex = point;
					off_t startLBA = msf_to_lba(make_msf_address(
						entries[i].pminutes, entries[i].pseconds,
						entries[i].pframes));
					// The control and adr values grabbed here are only used
					// later on to signal a warning if they don't match the
					// corresponding values of the parent session.
					track* track = new(std::nothrow) struct track(trackIndex,
						startLBA, entries[i].control, entries[i].adr);
					if (track == NULL)
						return B_NO_MEMORY;

					session->track_list.Add(track);
				} else {
					WARN(("%s: warning: illegal point 0x%2x found in table of "
						"contents\n", kModuleDebugName, entries[i].point));
				}
				break;
		}
	}
	return B_OK;
}
Exemple #7
0
int cueify_device_read_track_indices(cueify_device *d, cueify_indices *i,
				     uint8_t track) {
    cueify_device_private *dev = (cueify_device_private *)d;
    cueify_indices_private *indices = (cueify_indices_private *)i;
    cueify_full_toc_private toc;

    if (cueify_device_read_full_toc_unportable(dev, &toc) != CUEIFY_OK) {
	return CUEIFY_ERR_INTERNAL;
    }

    if ((track >= toc.first_track_number &&
	 track <= toc.last_track_number) ||
	track == CUEIFY_LEAD_OUT_TRACK) {
	/* First, see if there appears to be more than one index. */
	cueify_msf_t msf;
	cueify_position_t pos;
	int lba, first_lba, left_lba, right_lba, last_lba;
	int index;

	first_lba = left_lba = msf_to_lba(toc.tracks[track].offset);
	if (track ==
	    toc.sessions[toc.tracks[track].session].last_track_number) {
	    last_lba = right_lba =
		msf_to_lba(toc.sessions[toc.tracks[track].session].leadout);
	} else {
	    last_lba = right_lba = msf_to_lba(toc.tracks[track + 1].offset);
	}

	/* Get the index of the penultimate second of the track. */
	lba = last_lba - 1;
	if (lba < left_lba) {
	    lba = (left_lba + last_lba) / 2;
	}

	/* And the MSF of the first. */
	lba_to_msf(first_lba, &msf);

	if (cueify_device_read_position_unportable(
		dev, track, lba, &pos) != CUEIFY_OK) {
	    return CUEIFY_ERR_INTERNAL;
	}

	if (pos.track == track &&
	    pos.index != 1) {
	    indices->num_indices = pos.index;
	    indices->has_pregap = 0;
	    indices->indices = calloc(indices->num_indices,
				      sizeof(cueify_msf_t));
	    if (indices->indices == NULL) {
		return CUEIFY_ERR_INTERNAL;
	    }
	    indices->indices[0] = msf;
	} else if (pos.track == track + 1) {
	    indices->num_indices = 2;
	    indices->has_pregap = 1;
	    indices->indices = calloc(indices->num_indices,
				      sizeof(cueify_msf_t));
	    if (indices->indices == NULL) {
		return CUEIFY_ERR_INTERNAL;
	    }
	    indices->indices[0] = msf;

	    /* Detect the pre-gap. */
	    while (left_lba != right_lba) {
		lba = (left_lba + right_lba) / 2;

		if (cueify_device_read_position_unportable(
			dev, track, lba, &pos) != CUEIFY_OK) {
		    free(indices->indices);
		    indices->indices = NULL;
		    return CUEIFY_ERR_INTERNAL;
		}

		if (pos.track == track) {
		    /* Choose the right half. */
		    left_lba = lba + 1;
		} else {
		    /* Choose the left half. */
		    right_lba = lba;
		}
	    }

	    /* Found the start address. */
	    lba_to_msf(left_lba, &msf);
	    indices->indices[1] = msf;

	    /* Reset the right and left sides. */
	    last_lba = right_lba = lba;
	    left_lba = first_lba;

	    /* And calculate the TRUE index count. */
	    lba = last_lba - 1;
	    if (lba < left_lba) {
		lba = (left_lba + last_lba) / 2;
	    }

	    if (cueify_device_read_position_unportable(
		    dev, track, lba, &pos) != CUEIFY_OK) {
		free(indices->indices);
		indices->indices = NULL;
		return CUEIFY_ERR_INTERNAL;
	    }

	    if (pos.track == track &&
		pos.index != 1) {
		indices->num_indices = pos.index + 1;
		indices->indices = realloc(indices->indices,
					   indices->num_indices *
					   sizeof(cueify_msf_t));
		if (indices->indices == NULL) {
		    return CUEIFY_ERR_INTERNAL;
		}

		/* TODO: Test me. */
		/* Copy the pre-gap indices over. */
		memcpy(&(indices->indices[indices->num_indices]),
		       &(indices->indices[1]),
		       sizeof(cueify_msf_t));
	    } else {
		/* That's it. */
		return CUEIFY_OK;
	    }
	} else {
	    indices->num_indices = 1;
	    indices->has_pregap = 0;
	    indices->indices = calloc(1, sizeof(cueify_msf_t));
	    if (indices->indices == NULL) {
		return 0;
	    }
	    indices->indices[0] = msf;
	    return CUEIFY_OK;
	}

	for (index = 1; index < indices->num_indices; index++) {
	    /* Detect the given index by binary search. */
	    while (left_lba != right_lba) {
		lba = (left_lba + right_lba) / 2;

		if (cueify_device_read_position_unportable(
			dev, track, lba, &pos) != CUEIFY_OK) {
		    free(indices->indices);
		    indices->indices = NULL;
		    return CUEIFY_ERR_INTERNAL;
		}

		if (pos.index >= index + 1) {
		    /* Choose the left half. */
		    right_lba = lba;
		} else {
		    /* Choose the right half. */
		    left_lba = lba + 1;
		}
	    }

	    /* Found the start address. */
	    lba_to_msf(left_lba, &msf);
	    indices->indices[index] = msf;

	    /* Reset the right side. */
	    right_lba = last_lba;
	}
	
	return CUEIFY_OK;
    } else {
	return CUEIFY_ERR_INTERNAL;
    }
}  /* cueify_device_read_track_indices */
Exemple #8
0
cdrom_ioctl(int fd, u_long cmd, void *arg)
	{
	int	ret;
	cgc_t	cgc;

	switch	(cmd)
		{
		case	CDROMREADRAW:
		case	CDROMREADMODE1:
		case	CDROMREADMODE2:
			{
			struct cdrom_msf *msf;
			int blocksize = 0, format = 0, lba;
		
			switch	(cmd)
				{
				case	CDROMREADRAW:
					blocksize = CD_FRAMESIZE_RAW;
					break;
				case	CDROMREADMODE1:
					blocksize = CD_FRAMESIZE;
					format = 2;
					break;
				case	CDROMREADMODE2:
					blocksize = CD_FRAMESIZE_RAW0;
					break;
				}
			msf = (struct cdrom_msf *)arg;
			lba = msf_to_lba(msf->cdmsf_min0,msf->cdmsf_sec0,
				msf->cdmsf_frame0);
			ret = EINVAL;
			if	(lba < 0)
				break;

			cgc_init(&cgc, arg, blocksize, SUC_READ);
			ret = cdrom_read_block(fd, &cgc, lba, 1, format,							blocksize);
			if	(ret)
				{
/*
 * SCSI-II devices are not required to support CMD_READ_CD (which specifies
 * the blocksize to read) so try switching the block size with a mode select,
 * doing the normal read sector command and then changing the sector size back
 * to 2048.
 *
 * If the program dies before changing the blocksize back sdopen()
 * in the kernel will fail opens with a message that looks something like:
 *
 * "sr1: blksize 2336 not multiple of 512: cannot use"
 *
 * At that point the drive has to be power cycled (or reset in some other way).
*/
				if	(ret = cdrom_blocksize(fd, blocksize))
					break;
				ret = cdrom_read_cd(fd, &cgc, lba, blocksize, 1);
				ret |= cdrom_blocksize(fd, 2048);
				}
			break;
			}
		case	CDROMREADTOCHDR:
			{
			struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
			u_char buffer[12];
			
			cgc_init(&cgc, buffer, sizeof (buffer), SUC_READ);
			cgc.cdb[0] = CMD_READ_TOC_PMA_ATIP;
			cgc.cdb[1] = 0x2;	/* MSF */
			cgc.cdb[8] = 12;	/* LSB of length */

			ret = scsi_cmd(fd, &cgc);
			if	(!ret)
				{
				tochdr->cdth_trk0 = buffer[2];
				tochdr->cdth_trk1 = buffer[3];
				}
			break;
			}
		case	CDROMREADTOCENTRY:
			{
			struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg;
			u_char	buffer[12];

			cgc_init(&cgc, buffer, sizeof (buffer), SUC_READ);
			cgc.cdb[0] = CMD_READ_TOC_PMA_ATIP;
			cgc.cdb[1] = (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
			cgc.cdb[6] = tocentry->cdte_track;
			cgc.cdb[8] = 12;		/* LSB of length */

			ret = scsi_cmd(fd, &cgc);
			if	(ret)
				break;

			tocentry->cdte_ctrl = buffer[5] & 0xf;
			tocentry->cdte_adr = buffer[5] >> 4;
			tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
			if	(tocentry->cdte_format == CDROM_MSF)
				{
				tocentry->cdte_addr.msf.minute = buffer[9];
				tocentry->cdte_addr.msf.second = buffer[10];
				tocentry->cdte_addr.msf.frame = buffer[11];
				}
			else
				tocentry->cdte_addr.lba = (((((buffer[8] << 8)
						+ buffer[9]) << 8)
						+ buffer[10]) << 8)
						+ buffer[11];
			break;
			}
		case	CDROMEJECT:		/* NO-OP for now */
			ret = cdrom_tray_move(fd, 1);
			break;
		case	CDROMCLOSETRAY:
			ret = cdrom_tray_move(fd, 0);
			break;
/*
 * This sucks but emulates the expected behaviour.  Instead of the return
 * value being the actual status a success/fail indicator should have been
 * returned and the 3rd arg to the ioctl should have been an 'int *' to update
 * with the actual status.   Both the drive and disc status ioctl calls are
 * similarily braindamaged.
*/
		case	CDROM_DRIVE_STATUS:
			return(CDS_NO_INFO);	/* XXX */
		case	CDROM_DISC_STATUS:
			{
			tracktype tracks;
			int	cnt;

			cdrom_count_tracks(fd, &tracks);
			if	(tracks.error)
				return(tracks.error);
			if	(tracks.audio > 0)
				{
				cnt = tracks.data + tracks.cdi + tracks.xa;
				if	(cnt == 0)
					return(CDS_AUDIO);
				else
					return(CDS_MIXED);
				}
			if	(tracks.cdi)
				return(CDS_XA_2_2);
			if	(tracks.xa)
				return(CDS_XA_2_1);
			if	(tracks.data)
				return(CDS_DATA_1);
			return(CDS_NO_INFO);
			}
		}
	errno = ret;
	return(ret ? -1 : 0);
	}