2 * Copyright (c) 2010, Wei Mingzhi <whistler@openoffice.org>.
5 * Based on: Cdrom for Psemu Pro like Emulators
6 * By: linuzappz <linuzappz@hotmail.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses>.
24 #include <cdio/cdio.h>
29 static CdIo_t *cdHandle = NULL;
31 static void SetSpeed(int speed) {
33 if (speed == 0) speed = 0xFFFF;
35 cdio_set_speed(cdHandle, speed);
38 static void SetSpinDown(unsigned char spindown) {
42 memset(&cdb, 0, sizeof(cdb));
46 cdb.field[8] = sizeof(buf);
48 if (mmc_run_cmd(cdHandle, 10000, &cdb, SCSI_MMC_DATA_READ, sizeof(buf), buf) != DRIVER_OP_SUCCESS)
51 buf[11] = (buf[11] & 0xF0) | (spindown & 0x0F);
53 memset(&cdb, 0, sizeof(cdb));
58 cdb.field[8] = sizeof(buf);
60 mmc_run_cmd(cdHandle, 10000, &cdb, SCSI_MMC_DATA_WRITE, sizeof(buf), buf);
63 static void UnlockDoor() {
66 memset(&cdb, 0, sizeof(cdb));
71 mmc_run_cmd(cdHandle, 10000, &cdb, SCSI_MMC_DATA_WRITE, 0, NULL);
74 int OpenCdHandle(const char *dev) {
75 if (dev == NULL || dev[0] == '\0') {
76 if ((dev = cdio_get_default_device(NULL)) == NULL) {
82 cdHandle = cdio_open_am_cd(dev, "CAM");
84 cdHandle = cdio_open_cd(dev);
87 if (cdHandle != NULL) {
89 SetSpinDown(SpinDown);
98 void CloseCdHandle() {
99 if (cdHandle != NULL) {
100 cdio_set_speed(cdHandle, 0xFFFF);
101 SetSpinDown(SPINDOWN_VENDOR_SPECIFIC);
103 cdio_destroy(cdHandle);
109 int IsCdHandleOpen() {
110 return (cdHandle != NULL);
113 long GetTN(unsigned char *buffer) {
114 buffer[0] = cdio_get_first_track_num(cdHandle);
115 buffer[1] = cdio_get_last_track_num(cdHandle);
120 long GetTD(unsigned char track, unsigned char *buffer) {
123 if (track == 0) track = CDIO_CDROM_LEADOUT_TRACK;
125 if (!cdio_get_track_msf(cdHandle, track, &msf)) {
126 memset(buffer + 1, 0, 3);
130 buffer[0] = btoi(msf.f);
131 buffer[1] = btoi(msf.s);
132 buffer[2] = btoi(msf.m);
137 long GetTE(unsigned char track, unsigned char *m, unsigned char *s, unsigned char *f) {
138 unsigned char msf[3];
140 lba_to_msf(cdio_get_track_lba(cdHandle, track + 1) - CD_MSF_OFFSET, msf);
149 long ReadSector(crdata *cr) {
153 lba = msf_to_lba(cr->msf.cdmsf_min0, cr->msf.cdmsf_sec0, cr->msf.cdmsf_frame0);
154 memset(&cdb, 0, sizeof(cdb));
158 cdb.IncludeUserData = 1;
160 cdb.IncludeSyncData = 1;
161 cdb.SubChannelSelection = 0;
162 cdb.StartingLBA[1] = lba >> 16;
163 cdb.StartingLBA[2] = lba >> 8;
164 cdb.StartingLBA[3] = lba;
165 cdb.TransferBlocks[2] = 1;
167 if (mmc_run_cmd(cdHandle, 10000, (mmc_cdb_t *)&cdb, SCSI_MMC_DATA_READ, sizeof(*cr), cr) != DRIVER_OP_SUCCESS)
173 long PlayCDDA(unsigned char *sector) {
176 if (!cdio_get_track_msf(cdHandle, CDIO_CDROM_LEADOUT_TRACK, &end))
179 start.m = itob(sector[0]);
180 start.s = itob(sector[1]);
181 start.f = itob(sector[2]);
183 if (cdio_audio_play_msf(cdHandle, &start, &end) != DRIVER_OP_SUCCESS)
190 cdio_subchannel_t subchnl;
192 if (cdio_audio_read_subchannel(cdHandle, &subchnl) != DRIVER_OP_SUCCESS)
195 switch (subchnl.audio_status) {
196 case CDIO_MMC_READ_SUB_ST_PLAY:
197 case CDIO_MMC_READ_SUB_ST_PAUSED:
198 cdio_audio_stop(cdHandle);
204 long GetStatus(int playing, struct CdrStat *stat) {
205 cdio_subchannel_t subchnl;
207 memset(stat, 0, sizeof(struct CdrStat));
210 if (cdio_audio_read_subchannel(cdHandle, &subchnl) == DRIVER_OP_SUCCESS) {
211 stat->Time[0] = btoi(subchnl.abs_addr.m);
212 stat->Time[1] = btoi(subchnl.abs_addr.s);
213 stat->Time[2] = btoi(subchnl.abs_addr.f);
219 if (mmc_get_tray_status(cdHandle)) {
221 stat->Status |= 0x10;
224 SetSpinDown(SpinDown);
231 unsigned char *ReadSub(const unsigned char *time) {
232 int lba = msf_to_lba(btoi(time[0]), btoi(time[1]), btoi(time[2]));
233 static unsigned char buf[CD_FRAMESIZE_RAW + 96];
237 memset(&cdb, 0, sizeof(cdb));
241 cdb.IncludeUserData = 1;
243 cdb.IncludeSyncData = 1;
244 cdb.StartingLBA[1] = lba >> 16;
245 cdb.StartingLBA[2] = lba >> 8;
246 cdb.StartingLBA[3] = lba;
247 cdb.TransferBlocks[2] = 1;
248 cdb.SubChannelSelection = 1;
250 if (mmc_run_cmd(cdHandle, 10000, (mmc_cdb_t *)&cdb, SCSI_MMC_DATA_READ, sizeof(buf), buf) != DRIVER_OP_SUCCESS)
253 DecodeRawSubData(buf + CD_FRAMESIZE_RAW);
254 return buf + CD_FRAMESIZE_RAW;