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