1 /* Copyright WSPse
2 * eMail: wsp@gmx.de
3 *
4 * These are the routines for cdrom I/O-handling
5 * Last updated: 20/11/99
6 * Updated: 2000/06/24 (BSD routines by Scott Aaron Bamford)
7 * 2001/01/07 (64bit-support for CDDB-ID)
8 */
9
10 /* Copying:
11 This program is free software; you can redistribute it and/or modify it under
12 the terms of the GNU Gerneral Public License as published by the Free Soft-
13 ware Foundation; either version 2 of License, or (at your option) any later
14 version.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILTY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 more details.
20
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc., 675 Mass
23 Ave, Cambridge, MA 02139, USA.
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <stdio.h>
31 #include "mp3creat.h"
32
33 #ifdef HAVE_LINUX_CDROM_H
34 #include <linux/cdrom.h>
35 #endif
36 #ifdef HAVE_SYS_CDIO_H
37 #include <sys/cdio.h>
38 #endif
39 #ifdef HAVE_SYS_TYPES_H
40 #include <sys/types.h>
41 #endif
42 #ifdef HAVE_SYS_STAT_H
43 #include <sys/stat.h>
44 #endif
45
46 extern char *def_cdrom_dev;
47
48 #ifdef HAVE_LINUX_CDROM_H
49 /* Global structs from cdrom.h */
50 struct cdrom_tochdr tochdr; /* start and endtrack on cd */
51 struct cdrom_volctrl volctrl; /* structure for volume control */
52 struct cdrom_ti ti; /* play tracks */
53 struct cdrom_tocentry tocentry; /* toc entrys */
54 struct cdrom_subchnl sc; /* status, etc */
55 #else
56 /* Global structs from cdio.h */
57 struct ioc_toc_header tochdr; /* start and endtrack on cd */
58 struct ioc_vol volctrl; /* structure for volume control */
59 struct ioc_play_track ti; /* play tracks */
60 struct ioc_read_toc_entry tocentry; /* toc entrys */
61 struct cd_toc_entry cddata; /* data for toc entrys */
62 struct cd_sub_channel_info sc; /* status, etc */
63 #endif /* !HAVE_LINUX_CDROM_H */
64
65 /* Globals */
66 struct {
67 int min;
68 int sec;
69 int frame;
70 } cdtoc[100];
71
72 /* Declerations */
73 unsigned long cddb_discid(int tot_trks);
74 int track_first, track_last;
75 int cd_drv = -1; /* values: -2: toc was read (cd ok), -1: cd failure, >=0: filedes (cd-device open) */
76
77 /* Close cdrom device, and set global id */
close_cdrom()78 int close_cdrom()
79 {
80 if(cd_drv >= 0) {
81 close(cd_drv);
82 cd_drv = -2;
83 }
84
85 return cd_drv;
86 }
87
88 /* Open cdrom device, and set global id */
open_cdrom()89 int open_cdrom()
90 {
91 close_cdrom();
92 cd_drv = open(def_cdrom_dev, O_RDONLY | O_NONBLOCK);
93 if(cd_drv <= 0) cd_drv = -1;
94
95 return cd_drv;
96 }
97
98 /* Send ioctl to cdrom */
ioctl_cdrom(int cmd)99 int ioctl_cdrom(int cmd)
100 {
101 int tmp;
102
103 if(cd_drv >= 0) {
104 tmp = ioctl(cd_drv, cmd);
105 } else {
106 tmp = open_cdrom();
107 if(tmp >= 0) {
108 tmp = ioctl(cd_drv, cmd);
109 close_cdrom();
110 }
111 }
112
113 return tmp;
114 }
115
116 /* Eject CD-Rom */
eject_cd()117 int eject_cd ()
118 {
119 int tmp;
120
121 #ifdef HAVE_LINUX_CDROM_H
122 tmp = ioctl_cdrom(CDROMEJECT);
123 #else
124 tmp = ioctl_cdrom(CDIOCEJECT);
125 #endif /* !HAVE_LINUX_CDROM_H */
126 if(tmp != 0) return 1;
127 return 0; /* Eject ok */
128 }
129
130 /* Close the tray of cdrom-drive */
close_tray()131 int close_tray ()
132 {
133 int tmp;
134
135 #ifdef HAVE_LINUX_CDROM_H
136 tmp = ioctl_cdrom(CDROMCLOSETRAY);
137 #else
138 tmp = ioctl_cdrom(CDIOCCLOSE);
139 #endif /* !HAVE_LINUX_CDROM_H */
140 if(tmp != 0) return 1; /* closing the tray failed... */
141 return 0; /* Tray closed */
142 }
143
144 /* init new cdrom volume */
init_cd()145 int init_cd ()
146 {
147 int tmp;
148 int i;
149 BOOL closeing_needed;
150
151 track_first = 0;
152 track_last = 0;
153 closeing_needed = FALSE;
154
155 if(cd_drv < 0) {
156 if(open_cdrom() < 0) {
157 return -1;
158 }
159 closeing_needed = TRUE;
160 }
161
162 #ifdef HAVE_LINUX_CDROM_H
163 tmp = ioctl(cd_drv, CDROMREADTOCHDR, &tochdr); /* read header of toc */
164 #else
165 tmp = ioctl(cd_drv, CDIOREADTOCHEADER, &tochdr); /* read header of toc */
166 #endif /* !HAVE_LINUX_CDROM_H */
167 if(tmp != 0) {
168 if(closeing_needed) close_cdrom();
169 return -1;
170 }
171
172 #ifdef HAVE_LINUX_CDROM_H
173 track_first = tochdr.cdth_trk0;
174 track_last = tochdr.cdth_trk1;
175
176 tocentry.cdte_track = CDROM_LEADOUT;
177 tocentry.cdte_format = CDROM_MSF;
178 #else
179 track_first = tochdr.starting_track;
180 track_last = tochdr.ending_track;
181
182 #ifndef CDROM_LEADOUT
183 #define CDROM_LEADOUT 0xAA
184 #endif /* !CDROM_LEADOUT */
185
186 tocentry.starting_track = CDROM_LEADOUT;
187 tocentry.address_format = CD_MSF_FORMAT;
188 #endif /* !HAVE_LINUX_CDROM_H */
189
190 #ifdef HAVE_LINUX_CDROM_H
191 if(ioctl(cd_drv, CDROMREADTOCENTRY, &tocentry) != 0) {
192 #else
193 tocentry.data = &cddata;
194 tocentry.data_len = sizeof(cddata);
195 if(ioctl(cd_drv, CDIOREADTOCENTRYS, &tocentry) != 0) {
196 #endif /* !HAVE_LINUX_CDROM_H */
197 if(closeing_needed) close_cdrom();
198 return -1;
199 }
200
201 #ifdef HAVE_LINUX_CDROM_H
202 cdtoc[track_last].min = tocentry.cdte_addr.msf.minute;
203 cdtoc[track_last].sec = tocentry.cdte_addr.msf.second;
204 cdtoc[track_last].frame = tocentry.cdte_addr.msf.frame;
205 #else
206 cdtoc[track_last].min = tocentry.data->addr.msf.minute;
207 cdtoc[track_last].sec = tocentry.data->addr.msf.second;
208 cdtoc[track_last].frame = tocentry.data->addr.msf.frame;
209 #endif /* !HAVE_LINUX_CDROM_H */
210
211 for(i=track_last;i>=track_first;i--) {
212 #ifdef HAVE_LINUX_CDROM_H
213 tocentry.cdte_track = i;
214 tocentry.cdte_format = CDROM_MSF;
215
216 if(ioctl(cd_drv, CDROMREADTOCENTRY, &tocentry) != 0) {
217 #else
218 tocentry.starting_track = i;
219 tocentry.address_format = CD_MSF_FORMAT;
220
221 if(ioctl(cd_drv, CDIOREADTOCENTRYS, &tocentry) == -1) {
222 #endif /* !HAVE_LINUX_CDROM_H */
223 if(closeing_needed) close_cdrom();
224 return -1;
225 }
226
227 #ifdef HAVE_LINUX_CDROM_H
228 cdtoc[i-1].min = tocentry.cdte_addr.msf.minute;
229 cdtoc[i-1].sec = tocentry.cdte_addr.msf.second;
230 cdtoc[i-1].frame = tocentry.cdte_addr.msf.frame;
231 #else
232 cdtoc[i-1].min = tocentry.data->addr.msf.minute;
233 cdtoc[i-1].sec = tocentry.data->addr.msf.second;
234 cdtoc[i-1].frame = tocentry.data->addr.msf.frame;
235 #endif /* !HAVE_LINUX_CDROM_H */
236 }
237
238 if(closeing_needed) close_cdrom();
239 return 0;
240 }
241
242 /* hard reset drive */
243 int hard_reset ()
244 {
245 int tmp;
246
247 #ifdef HAVE_LINUX_CDROM_H
248 tmp = ioctl_cdrom(CDROMRESET);
249 #else
250 tmp = ioctl_cdrom(CDIOCRESET);
251 #endif /* !HAVE_LINUX_CDROM_H */
252 return tmp;
253 }
254
255 /* play (a) track(s) */
256 int play_track (int tr_begin, int tr_end)
257 {
258 int tmp;
259
260 #ifdef HAVE_LINUX_CDROM_H
261 ti.cdti_trk0 = tr_begin;
262 ti.cdti_trk1 = tr_end;
263 ti.cdti_ind0 = 0;
264 ti.cdti_ind1 = 0;
265 #else
266 ti.start_track = tr_begin;
267 ti.end_track = tr_end;
268 ti.start_index = 0;
269 ti.end_index = 0;
270 #endif /* !HAVE_LINUX_CDROM_H */
271
272 if(cd_drv < 0) {
273 if(open_cdrom() < 0) {
274 return -1;
275 }
276 #ifdef HAVE_LINUX_CDROM_H
277 tmp = ioctl(cd_drv, CDROMPLAYTRKIND, &ti);
278 #else
279 tmp = ioctl(cd_drv, CDIOCPLAYTRACKS, &ti);
280 #endif /* !HAVE_LINUX_CDROM_H */
281 close_cdrom();
282 } else {
283 #ifdef HAVE_LINUX_CDROM_H
284 tmp = ioctl(cd_drv, CDROMPLAYTRKIND, &ti);
285 #else
286 tmp = ioctl(cd_drv, CDIOCPLAYTRACKS, &ti);
287 #endif /* !HAVE_LINUX_CDROM_H */
288 }
289 if(tmp != 0) return -1;
290 return 0;
291 }
292
293 /* Stop CD */
294 int stop_cd ()
295 {
296 int tmp;
297 #ifdef HAVE_LINUX_CDROM_H
298 tmp = ioctl_cdrom(CDROMSTOP);
299 #else
300 tmp = ioctl_cdrom(CDIOCSTOP);
301 #endif /* !HAVE_LINUX_CDROM_H */
302 if(tmp != 0) return -1;
303 return 0;
304 }
305
306 /* Pause CD */
307 int pause_cd ()
308 {
309 int tmp;
310
311 #ifdef HAVE_LINUX_CDROM_H
312 tmp = ioctl_cdrom(CDROMPAUSE);
313 #else
314 tmp = ioctl_cdrom(CDIOCPAUSE);
315 #endif /* !HAVE_LINUX_CDROM_H */
316 if(tmp != 0) return -1;
317 return 0;
318 }
319
320 /* Resume Pause */
321 int resume_cd ()
322 {
323 int tmp;
324
325 #ifdef HAVE_LINUX_CDROM_H
326 tmp = ioctl_cdrom(CDROMRESUME);
327 #else
328 tmp = ioctl_cdrom(CDIOCRESUME);
329 #endif /* !HAVE_LINUX_CDROM_H */
330 if(tmp != 0) return -1;
331 return 0;
332 }
333
334 /*-----Original Routines for calculating disc-id-----*/
335 /*-----see "cddb.howto" for copyrights---------------*/
336 int cddb_sum(int n)
337 {
338 int ret;
339
340 ret = 0;
341
342 while (n > 0) {
343 ret = ret + (n % 10);
344 n = n / 10;
345 }
346
347 return (ret);
348 }
349
350 unsigned long cddb_discid(int tot_trks)
351 {
352 int i,t,n;
353
354 i = 0;
355 t = 0;
356 n = 0;
357
358 while (i < tot_trks) {
359 n = n + cddb_sum((cdtoc[i].min * 60) + cdtoc[i].sec);
360 i++;
361 }
362
363 t = ((cdtoc[tot_trks].min * 60) + cdtoc[tot_trks].sec) -
364 ((cdtoc[0].min * 60) + cdtoc[0].sec);
365
366 /* changed for 64-bit compatibilty
367 * Matthias Hensler, 2001/01/07
368 */
369 return ((n % 0xff) << 24 | t << 8 | tot_trks) & 0xffffffff;
370 }
371 /*-----end-----*/
372