src/cdrom/beos/SDL_syscdrom.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. CD_NUMTRACKS
  2. CD_TRACK
  3. CD_TRACK_N
  4. CD_TRACK_M
  5. CD_TRACK_S
  6. CD_TRACK_F
  7. POS_TRACK
  8. POS_ABS_M
  9. POS_ABS_S
  10. POS_ABS_F
  11. POS_REL_M
  12. POS_REL_S
  13. POS_REL_F
  14. CheckDrive
  15. AddDrive
  16. CheckSCSI
  17. SDL_SYS_CDInit
  18. SDL_SYS_CDioctl
  19. SDL_SYS_CDName
  20. SDL_SYS_CDOpen
  21. SDL_SYS_CDGetTOC
  22. SDL_SYS_CDStatus
  23. SDL_SYS_CDPlay
  24. SDL_SYS_CDPause
  25. SDL_SYS_CDResume
  26. SDL_SYS_CDStop
  27. SDL_SYS_CDEject
  28. SDL_SYS_CDClose
  29. SDL_SYS_CDQuit

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

/* [<][>][^][v][top][bottom][index][help] */