src/cdrom/beos/SDL_syscdrom.cc
author Sam Lantinga <slouken@libsdl.org>
Wed, 27 Aug 2008 15:10:03 +0000
changeset 2735 204be4fc2726
parent 1895 c121d94672cb
child 2859 99210400e8b9
permissions -rw-r--r--
Final merge of Google Summer of Code 2008 work...

Port SDL 1.3 to the Nintendo DS
by Darren Alton, mentored by Sam Lantinga
slouken@153
     1
/*
slouken@153
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@153
     4
slouken@153
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@153
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@153
     9
slouken@153
    10
    This library is distributed in the hope that it will be useful,
slouken@153
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@153
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@153
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@153
    18
slouken@153
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@153
    21
*/
slouken@1403
    22
#include "SDL_config.h"
slouken@153
    23
slouken@1635
    24
#ifdef SDL_CDROM_BEOS
slouken@1635
    25
slouken@153
    26
/* Functions for system-level CD-ROM audio control on BeOS
slouken@153
    27
   (not completely implemented yet)
slouken@153
    28
 */
slouken@153
    29
slouken@153
    30
#include <sys/types.h>
slouken@153
    31
#include <sys/stat.h>
slouken@153
    32
#include <unistd.h>
slouken@153
    33
slouken@153
    34
#include <scsi.h>
slouken@153
    35
#include <Directory.h>
slouken@153
    36
#include <Entry.h>
slouken@153
    37
#include <Path.h>
slouken@153
    38
slouken@153
    39
#include "SDL_cdrom.h"
slouken@1895
    40
extern "C"
slouken@1895
    41
{
slouken@1361
    42
#include "../SDL_syscdrom.h"
slouken@153
    43
}
slouken@153
    44
slouken@153
    45
/* Constants to help us get at the SCSI table-of-contents info */
slouken@153
    46
#define CD_NUMTRACKS(toc)	toc.toc_data[3]
slouken@153
    47
#define CD_TRACK(toc, track)	(&toc.toc_data[6+(track)*8])
slouken@153
    48
#define CD_TRACK_N(toc, track)	CD_TRACK(toc, track)[0]
slouken@153
    49
#define CD_TRACK_M(toc, track)	CD_TRACK(toc, track)[3]
slouken@153
    50
#define CD_TRACK_S(toc, track)	CD_TRACK(toc, track)[4]
slouken@153
    51
#define CD_TRACK_F(toc, track)	CD_TRACK(toc, track)[5]
slouken@153
    52
slouken@153
    53
/* Constants to help us get at the SCSI position info */
slouken@153
    54
#define POS_TRACK(pos)	pos.position[6]
slouken@153
    55
#define POS_ABS_M(pos)	pos.position[9]
slouken@153
    56
#define POS_ABS_S(pos)	pos.position[10]
slouken@153
    57
#define POS_ABS_F(pos)	pos.position[11]
slouken@153
    58
#define POS_REL_M(pos)	pos.position[13]
slouken@153
    59
#define POS_REL_S(pos)	pos.position[14]
slouken@153
    60
#define POS_REL_F(pos)	pos.position[15]
slouken@153
    61
slouken@153
    62
/* The maximum number of CD-ROM drives we'll detect */
slouken@1895
    63
#define MAX_DRIVES	16
slouken@153
    64
slouken@153
    65
/* A list of available CD-ROM drives */
slouken@153
    66
static char *SDL_cdlist[MAX_DRIVES];
slouken@153
    67
slouken@153
    68
/* The system-dependent CD control functions */
slouken@153
    69
static const char *SDL_SYS_CDName(int drive);
slouken@153
    70
static int SDL_SYS_CDOpen(int drive);
slouken@1895
    71
static int SDL_SYS_CDGetTOC(SDL_CD * cdrom);
slouken@1895
    72
static CDstatus SDL_SYS_CDStatus(SDL_CD * cdrom, int *position);
slouken@1895
    73
static int SDL_SYS_CDPlay(SDL_CD * cdrom, int start, int length);
slouken@1895
    74
static int SDL_SYS_CDPause(SDL_CD * cdrom);
slouken@1895
    75
static int SDL_SYS_CDResume(SDL_CD * cdrom);
slouken@1895
    76
static int SDL_SYS_CDStop(SDL_CD * cdrom);
slouken@1895
    77
static int SDL_SYS_CDEject(SDL_CD * cdrom);
slouken@1895
    78
static void SDL_SYS_CDClose(SDL_CD * cdrom);
slouken@153
    79
int try_dir(const char *directory);
slouken@153
    80
slouken@153
    81
slouken@153
    82
/* Check a drive to see if it is a CD-ROM */
slouken@1895
    83
static int
slouken@1895
    84
CheckDrive(char *drive)
slouken@153
    85
{
slouken@1895
    86
    struct stat stbuf;
slouken@1895
    87
    int is_cd, cdfd;
slouken@1895
    88
    device_geometry info;
slouken@153
    89
slouken@1895
    90
    /* If it doesn't exist, return -1 */
slouken@1895
    91
    if (stat(drive, &stbuf) < 0) {
slouken@1895
    92
        return (-1);
slouken@1895
    93
    }
slouken@153
    94
slouken@1895
    95
    /* If it does exist, verify that it's an available CD-ROM */
slouken@1895
    96
    is_cd = 0;
slouken@1895
    97
    cdfd = open(drive, 0);
slouken@1895
    98
    if (cdfd >= 0) {
slouken@1895
    99
        if (ioctl(cdfd, B_GET_GEOMETRY, &info) == B_NO_ERROR) {
slouken@1895
   100
            if (info.device_type == B_CD) {
slouken@1895
   101
                is_cd = 1;
slouken@1895
   102
            }
slouken@1895
   103
        }
slouken@1895
   104
        close(cdfd);
slouken@1895
   105
    } else {
slouken@1895
   106
        /* This can happen when the drive is open .. (?) */ ;
slouken@1895
   107
        is_cd = 1;
slouken@1895
   108
    }
slouken@1895
   109
    return (is_cd);
slouken@153
   110
}
slouken@153
   111
slouken@153
   112
/* Add a CD-ROM drive to our list of valid drives */
slouken@1895
   113
static void
slouken@1895
   114
AddDrive(char *drive)
slouken@153
   115
{
slouken@1895
   116
    int i;
slouken@1895
   117
    size_t len;
slouken@153
   118
slouken@1895
   119
    if (SDL_numcds < MAX_DRIVES) {
slouken@1895
   120
        /* Add this drive to our list */
slouken@1895
   121
        i = SDL_numcds;
slouken@1895
   122
        len = SDL_strlen(drive) + 1;
slouken@1895
   123
        SDL_cdlist[i] = (char *) SDL_malloc(len);
slouken@1895
   124
        if (SDL_cdlist[i] == NULL) {
slouken@1895
   125
            SDL_OutOfMemory();
slouken@1895
   126
            return;
slouken@1895
   127
        }
slouken@1895
   128
        SDL_strlcpy(SDL_cdlist[i], drive, len);
slouken@1895
   129
        ++SDL_numcds;
slouken@153
   130
#ifdef CDROM_DEBUG
slouken@1895
   131
        fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
slouken@153
   132
#endif
slouken@1895
   133
    }
slouken@153
   134
}
slouken@153
   135
slouken@153
   136
/* IDE bus scanning magic */
slouken@1895
   137
enum
slouken@1895
   138
{
slouken@1895
   139
    IDE_GET_DEVICES_INFO = B_DEVICE_OP_CODES_END + 50,
slouken@153
   140
};
slouken@1895
   141
struct ide_ctrl_info
slouken@1895
   142
{
slouken@1895
   143
    bool ide_0_present;
slouken@1895
   144
    bool ide_0_master_present;
slouken@1895
   145
    bool ide_0_slave_present;
slouken@1895
   146
    int ide_0_master_type;
slouken@1895
   147
    int ide_0_slave_type;
slouken@1895
   148
    bool ide_1_present;
slouken@1895
   149
    bool ide_1_master_present;
slouken@1895
   150
    bool ide_1_slave_present;
slouken@1895
   151
    int ide_1_master_type;
slouken@1895
   152
    int ide_1_slave_type;
slouken@153
   153
};
slouken@153
   154
slouken@1895
   155
int
slouken@1895
   156
SDL_SYS_CDInit(void)
slouken@153
   157
{
slouken@1895
   158
    char *SDLcdrom;
slouken@1895
   159
    int raw_fd;
slouken@1895
   160
    struct ide_ctrl_info info;
slouken@153
   161
slouken@1895
   162
    /* Fill in our driver capabilities */
slouken@1895
   163
    SDL_CDcaps.Name = SDL_SYS_CDName;
slouken@1895
   164
    SDL_CDcaps.Open = SDL_SYS_CDOpen;
slouken@1895
   165
    SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
slouken@1895
   166
    SDL_CDcaps.Status = SDL_SYS_CDStatus;
slouken@1895
   167
    SDL_CDcaps.Play = SDL_SYS_CDPlay;
slouken@1895
   168
    SDL_CDcaps.Pause = SDL_SYS_CDPause;
slouken@1895
   169
    SDL_CDcaps.Resume = SDL_SYS_CDResume;
slouken@1895
   170
    SDL_CDcaps.Stop = SDL_SYS_CDStop;
slouken@1895
   171
    SDL_CDcaps.Eject = SDL_SYS_CDEject;
slouken@1895
   172
    SDL_CDcaps.Close = SDL_SYS_CDClose;
slouken@153
   173
slouken@1895
   174
    /* Look in the environment for our CD-ROM drive list */
slouken@1895
   175
    SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */
slouken@1895
   176
    if (SDLcdrom != NULL) {
slouken@1895
   177
        char *cdpath, *delim;
slouken@1895
   178
        size_t len = SDL_strlen(SDLcdrom) + 1;
slouken@1895
   179
        cdpath = SDL_stack_alloc(char, len);
slouken@1895
   180
        if (cdpath != NULL) {
slouken@1895
   181
            SDL_strlcpy(cdpath, SDLcdrom, len);
slouken@1895
   182
            SDLcdrom = cdpath;
slouken@1895
   183
            do {
slouken@1895
   184
                delim = SDL_strchr(SDLcdrom, ':');
slouken@1895
   185
                if (delim) {
slouken@1895
   186
                    *delim++ = '\0';
slouken@1895
   187
                }
slouken@1895
   188
                if (CheckDrive(SDLcdrom) > 0) {
slouken@1895
   189
                    AddDrive(SDLcdrom);
slouken@1895
   190
                }
slouken@1895
   191
                if (delim) {
slouken@1895
   192
                    SDLcdrom = delim;
slouken@1895
   193
                } else {
slouken@1895
   194
                    SDLcdrom = NULL;
slouken@1895
   195
                }
slouken@2735
   196
            } while (SDLcdrom);
slouken@1895
   197
            SDL_stack_free(cdpath);
slouken@1895
   198
        }
slouken@153
   199
slouken@1895
   200
        /* If we found our drives, there's nothing left to do */
slouken@1895
   201
        if (SDL_numcds > 0) {
slouken@1895
   202
            return (0);
slouken@1895
   203
        }
slouken@1895
   204
    }
slouken@1895
   205
slouken@1895
   206
    /* Scan the system for CD-ROM drives */
slouken@1895
   207
    try_dir("/dev/disk");
slouken@1895
   208
    return 0;
slouken@153
   209
}
slouken@153
   210
slouken@153
   211
slouken@1895
   212
int
slouken@1895
   213
try_dir(const char *directory)
slouken@1895
   214
{
slouken@1895
   215
    BDirectory dir;
slouken@1895
   216
    dir.SetTo(directory);
slouken@1895
   217
    if (dir.InitCheck() != B_NO_ERROR) {
slouken@1895
   218
        return false;
slouken@1895
   219
    }
slouken@1895
   220
    dir.Rewind();
slouken@1895
   221
    BEntry entry;
slouken@1895
   222
    while (dir.GetNextEntry(&entry) >= 0) {
slouken@1895
   223
        BPath path;
slouken@1895
   224
        const char *name;
slouken@1895
   225
        entry_ref e;
slouken@153
   226
slouken@1895
   227
        if (entry.GetPath(&path) != B_NO_ERROR)
slouken@1895
   228
            continue;
slouken@1895
   229
        name = path.Path();
slouken@153
   230
slouken@1895
   231
        if (entry.GetRef(&e) != B_NO_ERROR)
slouken@1895
   232
            continue;
slouken@153
   233
slouken@1895
   234
        if (entry.IsDirectory()) {
slouken@1895
   235
            if (SDL_strcmp(e.name, "floppy") == 0)
slouken@1895
   236
                continue;       /* ignore floppy (it is not silent)  */
slouken@1895
   237
            int devfd = try_dir(name);
slouken@1895
   238
            if (devfd >= 0)
slouken@1895
   239
                return devfd;
slouken@1895
   240
        } else {
slouken@1895
   241
            int devfd;
slouken@1895
   242
            device_geometry g;
slouken@153
   243
slouken@1895
   244
            if (SDL_strcmp(e.name, "raw") != 0)
slouken@1895
   245
                continue;       /* ignore partitions */
slouken@1895
   246
slouken@1895
   247
            devfd = open(name, O_RDONLY);
slouken@1895
   248
            if (devfd < 0)
slouken@1895
   249
                continue;
slouken@1895
   250
slouken@1895
   251
            if (ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) {
slouken@1895
   252
                if (g.device_type == B_CD) {
slouken@1895
   253
                    AddDrive(strdup(name));
slouken@1895
   254
                }
slouken@1895
   255
            }
slouken@1895
   256
            close(devfd);
slouken@1895
   257
        }
slouken@1895
   258
    }
slouken@1895
   259
    return B_ERROR;
slouken@153
   260
}
slouken@153
   261
slouken@153
   262
slouken@153
   263
/* General ioctl() CD-ROM command function */
slouken@1895
   264
static int
slouken@1895
   265
SDL_SYS_CDioctl(int index, int command, void *arg)
slouken@153
   266
{
slouken@1895
   267
    int okay;
slouken@1895
   268
    int fd;
slouken@153
   269
slouken@1895
   270
    okay = 0;
slouken@1895
   271
    fd = open(SDL_cdlist[index], 0);
slouken@1895
   272
    if (fd >= 0) {
slouken@1895
   273
        if (ioctl(fd, command, arg) == B_NO_ERROR) {
slouken@1895
   274
            okay = 1;
slouken@1895
   275
        }
slouken@1895
   276
        close(fd);
slouken@1895
   277
    }
slouken@1895
   278
    return (okay ? 0 : -1);
slouken@153
   279
}
slouken@153
   280
slouken@1895
   281
static const char *
slouken@1895
   282
SDL_SYS_CDName(int drive)
slouken@153
   283
{
slouken@1895
   284
    return (SDL_cdlist[drive]);
slouken@153
   285
}
slouken@153
   286
slouken@1895
   287
static int
slouken@1895
   288
SDL_SYS_CDOpen(int drive)
slouken@153
   289
{
slouken@1895
   290
    return (drive);
slouken@1895
   291
}
slouken@153
   292
slouken@1895
   293
static int
slouken@1895
   294
SDL_SYS_CDGetTOC(SDL_CD * cdrom)
slouken@1895
   295
{
slouken@1895
   296
    int i;
slouken@1895
   297
    scsi_toc toc;
slouken@1895
   298
slouken@1895
   299
    if (SDL_SYS_CDioctl(cdrom->id, B_SCSI_GET_TOC, &toc) == 0) {
slouken@1895
   300
        cdrom->numtracks = CD_NUMTRACKS(toc);
slouken@1895
   301
        if (cdrom->numtracks > SDL_MAX_TRACKS) {
slouken@1895
   302
            cdrom->numtracks = SDL_MAX_TRACKS;
slouken@1895
   303
        }
slouken@1895
   304
        for (i = 0; i <= cdrom->numtracks; ++i) {
slouken@1895
   305
            cdrom->track[i].id = CD_TRACK_N(toc, i);
slouken@1895
   306
            /* FIXME:  How do we tell on BeOS? */
slouken@1895
   307
            cdrom->track[i].type = SDL_AUDIO_TRACK;
slouken@1895
   308
            cdrom->track[i].offset = MSF_TO_FRAMES(CD_TRACK_M(toc, i),
slouken@1895
   309
                                                   CD_TRACK_S(toc, i),
slouken@1895
   310
                                                   CD_TRACK_F(toc, i));
slouken@1895
   311
            cdrom->track[i].length = 0;
slouken@1895
   312
            if (i > 0) {
slouken@1895
   313
                cdrom->track[i - 1].length =
slouken@1895
   314
                    cdrom->track[i].offset - cdrom->track[i - 1].offset;
slouken@1895
   315
            }
slouken@1895
   316
        }
slouken@1895
   317
        return (0);
slouken@1895
   318
    } else {
slouken@1895
   319
        return (-1);
slouken@1895
   320
    }
slouken@153
   321
}
slouken@153
   322
slouken@153
   323
/* Get CD-ROM status */
slouken@1895
   324
static CDstatus
slouken@1895
   325
SDL_SYS_CDStatus(SDL_CD * cdrom, int *position)
slouken@153
   326
{
slouken@1895
   327
    CDstatus status;
slouken@1895
   328
    int fd;
slouken@1895
   329
    int cur_frame;
slouken@1895
   330
    scsi_position pos;
slouken@153
   331
slouken@1895
   332
    fd = open(SDL_cdlist[cdrom->id], 0);
slouken@1895
   333
    cur_frame = 0;
slouken@1895
   334
    if (fd >= 0) {
slouken@1895
   335
        if (ioctl(fd, B_SCSI_GET_POSITION, &pos) == B_NO_ERROR) {
slouken@1895
   336
            cur_frame =
slouken@1895
   337
                MSF_TO_FRAMES(POS_ABS_M(pos), POS_ABS_S(pos), POS_ABS_F(pos));
slouken@1895
   338
        }
slouken@1895
   339
        if (!pos.position[1] || (pos.position[1] >= 0x13) ||
slouken@1895
   340
            ((pos.position[1] == 0x12) && (!pos.position[6]))) {
slouken@1895
   341
            status = CD_STOPPED;
slouken@1895
   342
        } else if (pos.position[1] == 0x11) {
slouken@1895
   343
            status = CD_PLAYING;
slouken@1895
   344
        } else {
slouken@1895
   345
            status = CD_PAUSED;
slouken@1895
   346
        }
slouken@1895
   347
        close(fd);
slouken@1895
   348
    } else {
slouken@1895
   349
        status = CD_TRAYEMPTY;
slouken@1895
   350
    }
slouken@1895
   351
    if (position) {
slouken@1895
   352
        *position = cur_frame;
slouken@1895
   353
    }
slouken@1895
   354
    return (status);
slouken@153
   355
}
slouken@153
   356
slouken@153
   357
/* Start play */
slouken@1895
   358
static int
slouken@1895
   359
SDL_SYS_CDPlay(SDL_CD * cdrom, int start, int length)
slouken@153
   360
{
slouken@1895
   361
    int okay;
slouken@1895
   362
    int fd;
slouken@1895
   363
    scsi_play_position pos;
slouken@153
   364
slouken@1895
   365
    okay = 0;
slouken@1895
   366
    fd = open(SDL_cdlist[cdrom->id], 0);
slouken@1895
   367
    if (fd >= 0) {
slouken@1895
   368
        FRAMES_TO_MSF(start, &pos.start_m, &pos.start_s, &pos.start_f);
slouken@1895
   369
        FRAMES_TO_MSF(start + length, &pos.end_m, &pos.end_s, &pos.end_f);
slouken@1895
   370
        if (ioctl(fd, B_SCSI_PLAY_POSITION, &pos) == B_NO_ERROR) {
slouken@1895
   371
            okay = 1;
slouken@1895
   372
        }
slouken@1895
   373
        close(fd);
slouken@1895
   374
    }
slouken@1895
   375
    return (okay ? 0 : -1);
slouken@153
   376
}
slouken@153
   377
slouken@153
   378
/* Pause play */
slouken@1895
   379
static int
slouken@1895
   380
SDL_SYS_CDPause(SDL_CD * cdrom)
slouken@153
   381
{
slouken@1895
   382
    return (SDL_SYS_CDioctl(cdrom->id, B_SCSI_PAUSE_AUDIO, 0));
slouken@153
   383
}
slouken@153
   384
slouken@153
   385
/* Resume play */
slouken@1895
   386
static int
slouken@1895
   387
SDL_SYS_CDResume(SDL_CD * cdrom)
slouken@153
   388
{
slouken@1895
   389
    return (SDL_SYS_CDioctl(cdrom->id, B_SCSI_RESUME_AUDIO, 0));
slouken@153
   390
}
slouken@153
   391
slouken@153
   392
/* Stop play */
slouken@1895
   393
static int
slouken@1895
   394
SDL_SYS_CDStop(SDL_CD * cdrom)
slouken@153
   395
{
slouken@1895
   396
    return (SDL_SYS_CDioctl(cdrom->id, B_SCSI_STOP_AUDIO, 0));
slouken@153
   397
}
slouken@153
   398
slouken@153
   399
/* Eject the CD-ROM */
slouken@1895
   400
static int
slouken@1895
   401
SDL_SYS_CDEject(SDL_CD * cdrom)
slouken@153
   402
{
slouken@1895
   403
    return (SDL_SYS_CDioctl(cdrom->id, B_SCSI_EJECT, 0));
slouken@153
   404
}
slouken@153
   405
slouken@153
   406
/* Close the CD-ROM handle */
slouken@1895
   407
static void
slouken@1895
   408
SDL_SYS_CDClose(SDL_CD * cdrom)
slouken@153
   409
{
slouken@1895
   410
    close(cdrom->id);
slouken@153
   411
}
slouken@153
   412
slouken@1895
   413
void
slouken@1895
   414
SDL_SYS_CDQuit(void)
slouken@153
   415
{
slouken@1895
   416
    int i;
slouken@153
   417
slouken@1895
   418
    if (SDL_numcds > 0) {
slouken@1895
   419
        for (i = 0; i < SDL_numcds; ++i) {
slouken@1895
   420
            SDL_free(SDL_cdlist[i]);
slouken@1895
   421
        }
slouken@1895
   422
        SDL_numcds = 0;
slouken@1895
   423
    }
slouken@153
   424
}
slouken@153
   425
slouken@1635
   426
#endif /* SDL_CDROM_BEOS */
slouken@1895
   427
/* vi: set ts=4 sw=4 expandtab: */