Mercurial > sdl-ios-xcode
annotate src/cdrom/linux/SDL_syscdrom.c @ 998:0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
From: Stephane Marchesin
Subject: Re: [SDL] Problem compiling SDL 1.2.7
- there is a bug that was introduced in the kernel headers for 2.6.9
which is fixed in 2.6.10. This bug *will* byte when compiling the cdrom
subsystem. A patch that works around this bug is attached. Note that
users affected are not those running 2.6.9, but those using the 2.6.9
kernel headers for their system (i.e. whose libc is built against 2.6.9
headers).
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 30 Nov 2004 14:45:08 +0000 |
parents | b8d311d90021 |
children | 091350827e08 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
396
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 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 | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
247
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* Functions for system-level CD-ROM audio control */ | |
29 | |
30 #include <sys/types.h> | |
31 #include <stdlib.h> | |
32 #include <sys/stat.h> | |
33 #include <sys/ioctl.h> | |
34 #include <fcntl.h> | |
35 #include <stdio.h> | |
36 #include <string.h> | |
37 #include <errno.h> | |
38 #include <unistd.h> | |
39 #ifdef __linux__ | |
998
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
40 /* linux 2.6.9 workaround */ |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
41 #include <linux/version.h> |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
42 #if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,9) |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
43 #include <asm/types.h> |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
44 #define __le64 __u64 |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
45 #define __le32 __u32 |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
46 #define __le16 __u16 |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
47 #define __be64 __u64 |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
48 #define __be32 __u32 |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
49 #define __be16 __u16 |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
50 #endif /* linux 2.6.9 workaround */ |
0 | 51 #include <linux/cdrom.h> |
52 #endif | |
53 #ifdef __SVR4 | |
54 #include <sys/cdio.h> | |
55 #endif | |
56 | |
57 /* Define this to use the alternative getmntent() code */ | |
58 #ifndef __SVR4 | |
59 #define USE_MNTENT | |
60 #endif | |
61 | |
62 #ifdef USE_MNTENT | |
63 #if defined(__USLC__) | |
64 #include <sys/mntent.h> | |
65 #else | |
66 #include <mntent.h> | |
67 #endif | |
68 | |
69 #ifndef _PATH_MNTTAB | |
70 #ifdef MNTTAB | |
71 #define _PATH_MNTTAB MNTTAB | |
72 #else | |
73 #define _PATH_MNTTAB "/etc/fstab" | |
74 #endif | |
75 #endif /* !_PATH_MNTTAB */ | |
76 | |
77 #ifndef _PATH_MOUNTED | |
78 #define _PATH_MOUNTED "/etc/mtab" | |
79 #endif /* !_PATH_MOUNTED */ | |
80 | |
81 #ifndef MNTTYPE_CDROM | |
82 #define MNTTYPE_CDROM "iso9660" | |
83 #endif | |
84 #ifndef MNTTYPE_SUPER | |
85 #define MNTTYPE_SUPER "supermount" | |
86 #endif | |
87 #endif /* USE_MNTENT */ | |
88 | |
89 #include "SDL_error.h" | |
90 #include "SDL_cdrom.h" | |
91 #include "SDL_syscdrom.h" | |
92 | |
93 | |
94 /* The maximum number of CD-ROM drives we'll detect */ | |
95 #define MAX_DRIVES 16 | |
96 | |
97 /* A list of available CD-ROM drives */ | |
98 static char *SDL_cdlist[MAX_DRIVES]; | |
99 static dev_t SDL_cdmode[MAX_DRIVES]; | |
100 | |
101 /* The system-dependent CD control functions */ | |
102 static const char *SDL_SYS_CDName(int drive); | |
103 static int SDL_SYS_CDOpen(int drive); | |
104 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); | |
105 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); | |
106 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); | |
107 static int SDL_SYS_CDPause(SDL_CD *cdrom); | |
108 static int SDL_SYS_CDResume(SDL_CD *cdrom); | |
109 static int SDL_SYS_CDStop(SDL_CD *cdrom); | |
110 static int SDL_SYS_CDEject(SDL_CD *cdrom); | |
111 static void SDL_SYS_CDClose(SDL_CD *cdrom); | |
112 | |
113 /* Some ioctl() errno values which occur when the tray is empty */ | |
396
11d6eed68dba
Added check for ENOMEDIUM to the Linux CDROM code
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
114 #ifndef ENOMEDIUM |
11d6eed68dba
Added check for ENOMEDIUM to the Linux CDROM code
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
115 #define ENOMEDIUM ENOENT |
11d6eed68dba
Added check for ENOMEDIUM to the Linux CDROM code
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
116 #endif |
0 | 117 #define ERRNO_TRAYEMPTY(errno) \ |
396
11d6eed68dba
Added check for ENOMEDIUM to the Linux CDROM code
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
118 ((errno == EIO) || (errno == ENOENT) || \ |
11d6eed68dba
Added check for ENOMEDIUM to the Linux CDROM code
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
119 (errno == EINVAL) || (errno == ENOMEDIUM)) |
0 | 120 |
121 /* Check a drive to see if it is a CD-ROM */ | |
122 static int CheckDrive(char *drive, char *mnttype, struct stat *stbuf) | |
123 { | |
124 int is_cd, cdfd; | |
125 struct cdrom_subchnl info; | |
126 | |
127 /* If it doesn't exist, return -1 */ | |
128 if ( stat(drive, stbuf) < 0 ) { | |
129 return(-1); | |
130 } | |
131 | |
132 /* If it does exist, verify that it's an available CD-ROM */ | |
133 is_cd = 0; | |
134 if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) { | |
135 cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0); | |
136 if ( cdfd >= 0 ) { | |
137 info.cdsc_format = CDROM_MSF; | |
138 /* Under Linux, EIO occurs when a disk is not present. | |
139 */ | |
140 if ( (ioctl(cdfd, CDROMSUBCHNL, &info) == 0) || | |
141 ERRNO_TRAYEMPTY(errno) ) { | |
142 is_cd = 1; | |
143 } | |
144 close(cdfd); | |
145 } | |
146 #ifdef USE_MNTENT | |
147 /* Even if we can't read it, it might be mounted */ | |
148 else if ( mnttype && (strcmp(mnttype, MNTTYPE_CDROM) == 0) ) { | |
149 is_cd = 1; | |
150 } | |
151 #endif | |
152 } | |
153 return(is_cd); | |
154 } | |
155 | |
156 /* Add a CD-ROM drive to our list of valid drives */ | |
157 static void AddDrive(char *drive, struct stat *stbuf) | |
158 { | |
159 int i; | |
160 | |
161 if ( SDL_numcds < MAX_DRIVES ) { | |
162 /* Check to make sure it's not already in our list. | |
163 This can happen when we see a drive via symbolic link. | |
164 */ | |
165 for ( i=0; i<SDL_numcds; ++i ) { | |
166 if ( stbuf->st_rdev == SDL_cdmode[i] ) { | |
167 #ifdef DEBUG_CDROM | |
168 fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]); | |
169 #endif | |
170 return; | |
171 } | |
172 } | |
173 | |
174 /* Add this drive to our list */ | |
175 i = SDL_numcds; | |
176 SDL_cdlist[i] = (char *)malloc(strlen(drive)+1); | |
177 if ( SDL_cdlist[i] == NULL ) { | |
178 SDL_OutOfMemory(); | |
179 return; | |
180 } | |
181 strcpy(SDL_cdlist[i], drive); | |
182 SDL_cdmode[i] = stbuf->st_rdev; | |
183 ++SDL_numcds; | |
184 #ifdef DEBUG_CDROM | |
185 fprintf(stderr, "Added CD-ROM drive: %s\n", drive); | |
186 #endif | |
187 } | |
188 } | |
189 | |
190 #ifdef USE_MNTENT | |
191 static void CheckMounts(const char *mtab) | |
192 { | |
193 FILE *mntfp; | |
194 struct mntent *mntent; | |
195 struct stat stbuf; | |
196 | |
197 mntfp = setmntent(mtab, "r"); | |
198 if ( mntfp != NULL ) { | |
139
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
199 char *tmp; |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
200 char *mnt_type; |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
201 char *mnt_dev; |
0 | 202 |
203 while ( (mntent=getmntent(mntfp)) != NULL ) { | |
139
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
204 mnt_type = malloc(strlen(mntent->mnt_type) + 1); |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
205 if (mnt_type == NULL) |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
206 continue; /* maybe you'll get lucky next time. */ |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
207 |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
208 mnt_dev = malloc(strlen(mntent->mnt_fsname) + 1); |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
209 if (mnt_dev == NULL) { |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
210 free(mnt_type); |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
211 continue; |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
212 } |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
213 |
0 | 214 strcpy(mnt_type, mntent->mnt_type); |
215 strcpy(mnt_dev, mntent->mnt_fsname); | |
216 | |
217 /* Handle "supermount" filesystem mounts */ | |
218 if ( strcmp(mnt_type, MNTTYPE_SUPER) == 0 ) { | |
219 tmp = strstr(mntent->mnt_opts, "fs="); | |
220 if ( tmp ) { | |
247
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
221 free(mnt_type); |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
222 mnt_type = strdup(tmp + strlen("fs=")); |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
223 if ( mnt_type ) { |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
224 tmp = strchr(mnt_type, ','); |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
225 if ( tmp ) { |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
226 *tmp = '\0'; |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
227 } |
0 | 228 } |
229 } | |
230 tmp = strstr(mntent->mnt_opts, "dev="); | |
231 if ( tmp ) { | |
247
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
232 free(mnt_dev); |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
233 mnt_dev = strdup(tmp + strlen("dev=")); |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
234 if ( mnt_dev ) { |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
235 tmp = strchr(mnt_dev, ','); |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
236 if ( tmp ) { |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
237 *tmp = '\0'; |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
238 } |
0 | 239 } |
240 } | |
241 } | |
242 if ( strcmp(mnt_type, MNTTYPE_CDROM) == 0 ) { | |
243 #ifdef DEBUG_CDROM | |
244 fprintf(stderr, "Checking mount path from %s: %s mounted on %s of %s\n", | |
245 mtab, mnt_dev, mntent->mnt_dir, mnt_type); | |
246 #endif | |
247 if (CheckDrive(mnt_dev, mnt_type, &stbuf) > 0) { | |
248 AddDrive(mnt_dev, &stbuf); | |
249 } | |
250 } | |
139
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
251 free(mnt_dev); |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
252 free(mnt_type); |
0 | 253 } |
254 endmntent(mntfp); | |
255 } | |
256 } | |
257 #endif /* USE_MNTENT */ | |
258 | |
259 int SDL_SYS_CDInit(void) | |
260 { | |
261 /* checklist: /dev/cdrom, /dev/hd?, /dev/scd? /dev/sr? */ | |
262 static char *checklist[] = { | |
263 "cdrom", "?a hd?", "?0 scd?", "?0 sr?", NULL | |
264 }; | |
265 char *SDLcdrom; | |
266 int i, j, exists; | |
267 char drive[32]; | |
268 struct stat stbuf; | |
269 | |
270 /* Fill in our driver capabilities */ | |
271 SDL_CDcaps.Name = SDL_SYS_CDName; | |
272 SDL_CDcaps.Open = SDL_SYS_CDOpen; | |
273 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; | |
274 SDL_CDcaps.Status = SDL_SYS_CDStatus; | |
275 SDL_CDcaps.Play = SDL_SYS_CDPlay; | |
276 SDL_CDcaps.Pause = SDL_SYS_CDPause; | |
277 SDL_CDcaps.Resume = SDL_SYS_CDResume; | |
278 SDL_CDcaps.Stop = SDL_SYS_CDStop; | |
279 SDL_CDcaps.Eject = SDL_SYS_CDEject; | |
280 SDL_CDcaps.Close = SDL_SYS_CDClose; | |
281 | |
282 /* Look in the environment for our CD-ROM drive list */ | |
283 SDLcdrom = getenv("SDL_CDROM"); /* ':' separated list of devices */ | |
284 if ( SDLcdrom != NULL ) { | |
285 char *cdpath, *delim; | |
286 cdpath = malloc(strlen(SDLcdrom)+1); | |
287 if ( cdpath != NULL ) { | |
288 strcpy(cdpath, SDLcdrom); | |
289 SDLcdrom = cdpath; | |
290 do { | |
291 delim = strchr(SDLcdrom, ':'); | |
292 if ( delim ) { | |
293 *delim++ = '\0'; | |
294 } | |
295 #ifdef DEBUG_CDROM | |
296 fprintf(stderr, "Checking CD-ROM drive from SDL_CDROM: %s\n", SDLcdrom); | |
297 #endif | |
298 if ( CheckDrive(SDLcdrom, NULL, &stbuf) > 0 ) { | |
299 AddDrive(SDLcdrom, &stbuf); | |
300 } | |
301 if ( delim ) { | |
302 SDLcdrom = delim; | |
303 } else { | |
304 SDLcdrom = NULL; | |
305 } | |
306 } while ( SDLcdrom ); | |
307 free(cdpath); | |
308 } | |
309 | |
310 /* If we found our drives, there's nothing left to do */ | |
311 if ( SDL_numcds > 0 ) { | |
312 return(0); | |
313 } | |
314 } | |
315 | |
316 #ifdef USE_MNTENT | |
317 /* Check /dev/cdrom first :-) */ | |
318 if (CheckDrive("/dev/cdrom", NULL, &stbuf) > 0) { | |
319 AddDrive("/dev/cdrom", &stbuf); | |
320 } | |
321 | |
322 /* Now check the currently mounted CD drives */ | |
323 CheckMounts(_PATH_MOUNTED); | |
324 | |
325 /* Finally check possible mountable drives in /etc/fstab */ | |
326 CheckMounts(_PATH_MNTTAB); | |
327 | |
328 /* If we found our drives, there's nothing left to do */ | |
329 if ( SDL_numcds > 0 ) { | |
330 return(0); | |
331 } | |
332 #endif /* USE_MNTENT */ | |
333 | |
334 /* Scan the system for CD-ROM drives. | |
335 Not always 100% reliable, so use the USE_MNTENT code above first. | |
336 */ | |
337 for ( i=0; checklist[i]; ++i ) { | |
338 if ( checklist[i][0] == '?' ) { | |
339 char *insert; | |
340 exists = 1; | |
341 for ( j=checklist[i][1]; exists; ++j ) { | |
342 sprintf(drive, "/dev/%s", &checklist[i][3]); | |
343 insert = strchr(drive, '?'); | |
344 if ( insert != NULL ) { | |
345 *insert = j; | |
346 } | |
347 #ifdef DEBUG_CDROM | |
348 fprintf(stderr, "Checking possible CD-ROM drive: %s\n", drive); | |
349 #endif | |
350 switch (CheckDrive(drive, NULL, &stbuf)) { | |
351 /* Drive exists and is a CD-ROM */ | |
352 case 1: | |
353 AddDrive(drive, &stbuf); | |
354 break; | |
355 /* Drive exists, but isn't a CD-ROM */ | |
356 case 0: | |
357 break; | |
358 /* Drive doesn't exist */ | |
359 case -1: | |
360 exists = 0; | |
361 break; | |
362 } | |
363 } | |
364 } else { | |
365 sprintf(drive, "/dev/%s", checklist[i]); | |
366 #ifdef DEBUG_CDROM | |
367 fprintf(stderr, "Checking possible CD-ROM drive: %s\n", drive); | |
368 #endif | |
369 if ( CheckDrive(drive, NULL, &stbuf) > 0 ) { | |
370 AddDrive(drive, &stbuf); | |
371 } | |
372 } | |
373 } | |
374 return(0); | |
375 } | |
376 | |
377 /* General ioctl() CD-ROM command function */ | |
378 static int SDL_SYS_CDioctl(int id, int command, void *arg) | |
379 { | |
380 int retval; | |
381 | |
382 retval = ioctl(id, command, arg); | |
383 if ( retval < 0 ) { | |
384 SDL_SetError("ioctl() error: %s", strerror(errno)); | |
385 } | |
386 return(retval); | |
387 } | |
388 | |
389 static const char *SDL_SYS_CDName(int drive) | |
390 { | |
391 return(SDL_cdlist[drive]); | |
392 } | |
393 | |
394 static int SDL_SYS_CDOpen(int drive) | |
395 { | |
396 return(open(SDL_cdlist[drive], (O_RDONLY|O_EXCL|O_NONBLOCK), 0)); | |
397 } | |
398 | |
399 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) | |
400 { | |
401 struct cdrom_tochdr toc; | |
402 int i, okay; | |
403 struct cdrom_tocentry entry; | |
404 | |
405 okay = 0; | |
406 if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc) == 0 ) { | |
407 cdrom->numtracks = toc.cdth_trk1-toc.cdth_trk0+1; | |
408 if ( cdrom->numtracks > SDL_MAX_TRACKS ) { | |
409 cdrom->numtracks = SDL_MAX_TRACKS; | |
410 } | |
411 /* Read all the track TOC entries */ | |
412 for ( i=0; i<=cdrom->numtracks; ++i ) { | |
413 if ( i == cdrom->numtracks ) { | |
414 cdrom->track[i].id = CDROM_LEADOUT; | |
415 } else { | |
416 cdrom->track[i].id = toc.cdth_trk0+i; | |
417 } | |
418 entry.cdte_track = cdrom->track[i].id; | |
419 entry.cdte_format = CDROM_MSF; | |
420 if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCENTRY, | |
421 &entry) < 0 ) { | |
422 break; | |
423 } else { | |
424 if ( entry.cdte_ctrl & CDROM_DATA_TRACK ) { | |
425 cdrom->track[i].type = SDL_DATA_TRACK; | |
426 } else { | |
427 cdrom->track[i].type = SDL_AUDIO_TRACK; | |
428 } | |
429 cdrom->track[i].offset = MSF_TO_FRAMES( | |
430 entry.cdte_addr.msf.minute, | |
431 entry.cdte_addr.msf.second, | |
432 entry.cdte_addr.msf.frame); | |
433 cdrom->track[i].length = 0; | |
434 if ( i > 0 ) { | |
435 cdrom->track[i-1].length = | |
436 cdrom->track[i].offset- | |
437 cdrom->track[i-1].offset; | |
438 } | |
439 } | |
440 } | |
441 if ( i == (cdrom->numtracks+1) ) { | |
442 okay = 1; | |
443 } | |
444 } | |
445 return(okay ? 0 : -1); | |
446 } | |
447 | |
448 /* Get CD-ROM status */ | |
449 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) | |
450 { | |
451 CDstatus status; | |
452 struct cdrom_tochdr toc; | |
453 struct cdrom_subchnl info; | |
454 | |
455 info.cdsc_format = CDROM_MSF; | |
456 if ( ioctl(cdrom->id, CDROMSUBCHNL, &info) < 0 ) { | |
457 if ( ERRNO_TRAYEMPTY(errno) ) { | |
458 status = CD_TRAYEMPTY; | |
459 } else { | |
460 status = CD_ERROR; | |
461 } | |
462 } else { | |
463 switch (info.cdsc_audiostatus) { | |
464 case CDROM_AUDIO_INVALID: | |
465 case CDROM_AUDIO_NO_STATUS: | |
466 /* Try to determine if there's a CD available */ | |
467 if (ioctl(cdrom->id, CDROMREADTOCHDR, &toc)==0) | |
468 status = CD_STOPPED; | |
469 else | |
470 status = CD_TRAYEMPTY; | |
471 break; | |
472 case CDROM_AUDIO_COMPLETED: | |
473 status = CD_STOPPED; | |
474 break; | |
475 case CDROM_AUDIO_PLAY: | |
476 status = CD_PLAYING; | |
477 break; | |
478 case CDROM_AUDIO_PAUSED: | |
479 /* Workaround buggy CD-ROM drive */ | |
480 if ( info.cdsc_trk == CDROM_LEADOUT ) { | |
481 status = CD_STOPPED; | |
482 } else { | |
483 status = CD_PAUSED; | |
484 } | |
485 break; | |
486 default: | |
487 status = CD_ERROR; | |
488 break; | |
489 } | |
490 } | |
491 if ( position ) { | |
492 if ( status == CD_PLAYING || (status == CD_PAUSED) ) { | |
493 *position = MSF_TO_FRAMES( | |
494 info.cdsc_absaddr.msf.minute, | |
495 info.cdsc_absaddr.msf.second, | |
496 info.cdsc_absaddr.msf.frame); | |
497 } else { | |
498 *position = 0; | |
499 } | |
500 } | |
501 return(status); | |
502 } | |
503 | |
504 /* Start play */ | |
505 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) | |
506 { | |
507 struct cdrom_msf playtime; | |
508 | |
509 FRAMES_TO_MSF(start, | |
510 &playtime.cdmsf_min0, &playtime.cdmsf_sec0, &playtime.cdmsf_frame0); | |
511 FRAMES_TO_MSF(start+length, | |
512 &playtime.cdmsf_min1, &playtime.cdmsf_sec1, &playtime.cdmsf_frame1); | |
513 #ifdef DEBUG_CDROM | |
514 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", | |
515 playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0, | |
516 playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1); | |
517 #endif | |
518 return(SDL_SYS_CDioctl(cdrom->id, CDROMPLAYMSF, &playtime)); | |
519 } | |
520 | |
521 /* Pause play */ | |
522 static int SDL_SYS_CDPause(SDL_CD *cdrom) | |
523 { | |
524 return(SDL_SYS_CDioctl(cdrom->id, CDROMPAUSE, 0)); | |
525 } | |
526 | |
527 /* Resume play */ | |
528 static int SDL_SYS_CDResume(SDL_CD *cdrom) | |
529 { | |
530 return(SDL_SYS_CDioctl(cdrom->id, CDROMRESUME, 0)); | |
531 } | |
532 | |
533 /* Stop play */ | |
534 static int SDL_SYS_CDStop(SDL_CD *cdrom) | |
535 { | |
536 return(SDL_SYS_CDioctl(cdrom->id, CDROMSTOP, 0)); | |
537 } | |
538 | |
539 /* Eject the CD-ROM */ | |
540 static int SDL_SYS_CDEject(SDL_CD *cdrom) | |
541 { | |
542 return(SDL_SYS_CDioctl(cdrom->id, CDROMEJECT, 0)); | |
543 } | |
544 | |
545 /* Close the CD-ROM handle */ | |
546 static void SDL_SYS_CDClose(SDL_CD *cdrom) | |
547 { | |
548 close(cdrom->id); | |
549 } | |
550 | |
551 void SDL_SYS_CDQuit(void) | |
552 { | |
553 int i; | |
554 | |
555 if ( SDL_numcds > 0 ) { | |
556 for ( i=0; i<SDL_numcds; ++i ) { | |
557 free(SDL_cdlist[i]); | |
558 } | |
559 SDL_numcds = 0; | |
560 } | |
561 } | |
562 |