1 /*
2 * This file is part of WorkMan, the civilized CD player library
3 * Copyright (C) 1991-1997 by Steven Grimm <koreth@midwinter.com>
4 * Copyright (C) by Dirk Försterling <milliByte@DeathsDoor.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 *
21 * SVR4 specific. Much of this is similar to plat_hpux.c.
22 */
23
24 #if (defined(SVR4) || defined(__SVR4)) && !defined(sun) && !defined(__sun) && !defined(sony_news) && !defined(__sony_news)
25
26
27 #include <sys/types.h>
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <signal.h>
35 #include <sys/mkdev.h>
36 #include <sys/stat.h>
37 #include <sys/sdi.h>
38 #include <sys/sdi_edt.h>
39 #include <sys/scsi.h>
40 #include <errno.h>
41
42 #include "include/wm_config.h"
43 #include "include/wm_struct.h"
44 #include "include/wm_cdtext.h"
45
46 #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM
47
48
49 void *malloc();
50 char *strchr();
51
52 int min_volume = 0;
53 int max_volume = 255;
54
55 static int
create_cdrom_node(char * dev_name)56 create_cdrom_node(char *dev_name)
57 {
58 char pass_through[100];
59 int file_des;
60 dev_t pass_thru_device;
61 int err;
62 int ccode;
63
64
65 strncpy(pass_through, dev_name, sizeof(pass_through) - 2);
66 pass_through[sizeof(pass_through) - 2] = '\0';
67 strcat(pass_through, "p" );
68
69 if (setreuid(-1,0) < 0)
70 {
71 perror("setregid/setreuid/access");
72 return -1;
73 }
74
75 ccode = access(pass_through, F_OK);
76
77 if (ccode < 0)
78 {
79 if ((file_des = open(dev_name, O_RDONLY)) < 0)
80 {
81 perror("open cdrom devices failed");
82 return -1;
83 }
84
85 if (ioctl(file_des, B_GETDEV, &pass_thru_device) < 0)
86 {
87 perror("Call to get pass-through device number failed");
88 return -1;
89 }
90
91 (void)close(file_des);
92
93 if (mknod(pass_through, (S_IFCHR | S_IREAD | S_IWRITE),
94 pass_thru_device) < 0)
95 {
96 perror("Unable to make pass-through node");
97 return -1;
98 }
99
100 if (chown(pass_through, 0 , 0) < 0)
101 {
102 perror("chown");
103 return -1;
104 }
105
106 if (chmod(pass_through, 0660 ) < 0)
107 {
108 perror("chmod");
109 return -1;
110 }
111 }
112
113 file_des = open( pass_through, O_RDWR);
114 err = errno;
115
116 if ( (setreuid(-1,getuid()) < 0) || (setregid(-1,getgid()) < 0) )
117 {
118 perror("setreuid/setregid");
119 return -1;
120 }
121 errno = err;
122 return file_des;
123 } /* create_cdrom_node() */
124
125 const char*
find_cdrom()126 find_cdrom()
127 {
128 /*
129 ** the path of the device has to start w/ /dev
130 ** otherwise we are vulnerable to race conditions
131 ** Thomas Biege <thomas@suse.de>
132 */
133 const char* device = NULL;
134
135 device = getenv("CDROM");
136 if ( (device != NULL) &&
137 !(strncmp("/dev/", device, 5) ||
138 strstr(_device, "/../") ))
139 return device;
140
141 if (access("/dev/cdrom/cdrom1", F_OK) == 0)
142 {
143 return "/dev/cdrom/cdrom1";
144 }
145 else if (access("/dev/cdrom/cdrom2", F_OK) == 0)
146 {
147 return "/dev/cdrom/cdrom2";
148 }
149 else
150 {
151 fprintf(stderr, "Could not find a CD device!\n");
152 return NULL;
153 }
154 } /* find_cdrom() */
155
156 /*
157 * Initialize the drive. A no-op for the generic driver.
158 */
159 int
gen_init(struct wm_drive * d)160 gen_init(struct wm_drive *d)
161 {
162 return 0;
163 } /* gen_init() */
164
165 /*
166 * Open the CD and figure out which kind of drive is attached.
167 */
168 int
gen_open(struct wm_drive * d)169 gen_open(struct wm_drive *d)
170 {
171 if (d->fd >= 0) { /* Device already open? */
172 wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "gen_open(): [device is open (fd=%d)]\n", d->fd);
173 return 0;
174 }
175
176 d->fd = create_cdrom_node(d->cd_device); /* this will do open */
177 if (d->fd < 0) {
178 if (errno == EACCES)
179 else if (errno != EINTR)
180 return -6;
181
182 /* No CD in drive. (Is this true also for svr4 ? XXX ) */
183 return 1;
184 }
185
186 return 0;
187 } /* gen_open() */
188
189 /*
190 * Send a SCSI command out the bus.
191 */
192 int
gen_scsi(struct wm_drive * d,unsigned char * xcdb,int cdblen,char * retbuf,int retbuflen,int getreply)193 gen_scsi( struct wm_drive *d, unsigned char *xcdb, int cdblen,
194 char *retbuf, int retbuflen, int getreply)
195 {
196 int ccode;
197 int file_des = d->fd;
198 int i,j;
199 unsigned char sense_buffer[ SENSE_SZ ];
200 int errno_save;
201
202 /* getreply == 1 is read, == 0 is write */
203
204 struct sb sb;
205 struct scs scs;
206
207 sb.sb_type = ISCB_TYPE;
208
209 sb.SCB.sc_comp_code = SDI_PROGRES;
210 sb.SCB.sc_int = NULL;
211 sb.SCB.sc_wd = 0;
212 sb.SCB.sc_dev.sa_major = 0;
213 sb.SCB.sc_dev.sa_minor = 0;
214 sb.SCB.sc_dev.sa_lun = 0;
215 sb.SCB.sc_dev.sa_exlun = 0;
216 sb.SCB.sc_status = 0;
217 sb.SCB.sc_link = (struct sb *) NULL;
218 sb.SCB.sc_resid = 0;
219
220 sb.SCB.sc_cmdpt = (void *)xcdb;
221 sb.SCB.sc_cmdsz = cdblen;
222
223 sb.SCB.sc_datapt = retbuf ;
224 sb.SCB.sc_datasz = retbuflen ;
225
226 if (getreply == 1)
227 sb.SCB.sc_mode = SCB_READ;
228 else
229 sb.SCB.sc_mode = SCB_WRITE;
230
231 sb.SCB.sc_time = 500;
232
233 ccode = ioctl(file_des, SDI_SEND, &sb);
234
235 if ( (sb.SCB.sc_comp_code != 0xd000000e ) ||
236 ( sb.SCB.sc_status != 02) )
237 return ccode;
238
239 errno_save = errno;
240
241 sb.SCB.sc_comp_code = SDI_PROGRES;
242 sb.SCB.sc_int = NULL;
243 sb.SCB.sc_wd = 0;
244 sb.SCB.sc_dev.sa_major = 0;
245 sb.SCB.sc_dev.sa_minor = 0;
246 sb.SCB.sc_dev.sa_lun = 0;
247 sb.SCB.sc_dev.sa_exlun = 0;
248 sb.SCB.sc_status = 0;
249 sb.SCB.sc_link = (struct sb *) NULL;
250 sb.SCB.sc_resid = 0;
251
252 scs.ss_op = SS_REQSEN;
253 scs.ss_lun = 0;
254 scs.ss_addr1 = 0;
255 scs.ss_addr = 0;
256 scs.ss_len = SENSE_SZ;
257 scs.ss_cont = 0;
258
259 sb.SCB.sc_cmdpt = SCS_AD(&scs);
260 sb.SCB.sc_cmdsz = SCS_SZ;
261 sb.SCB.sc_datapt = sense_buffer;
262 sb.SCB.sc_datasz = 18;
263 sb.SCB.sc_mode = SCB_READ;
264 sb.SCB.sc_time = 5000;
265
266 if (ioctl(file_des, SDI_SEND, &sb) < 0)
267 {
268 fprintf(stderr,"Cannot read sense.\n");
269 exit(-1);
270 }
271
272 errno=errno_save;
273 return -1;
274 } /* gen_scsi() */
275
276 int
gen_close(struct wm_drive * d)277 gen_close( struct wm_drive *d )
278 {
279 if(d->fd != -1) {
280 wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closing the device\n");
281 close(d->fd);
282 d->fd = -1;
283 }
284 return 0;
285 }
286
287 /*
288 * Get the current status of the drive: the current play mode, the absolute
289 * position from start of disc (in frames), and the current track and index
290 * numbers if the CD is playing or paused.
291 */
292 int
gen_get_drive_status(struct wm_drive * d,int oldmode,int * mode,int * pos,int * track,int * index)293 gen_get_drive_status(struct wm_drive *d, int oldmode,
294 int *mode, int *pos, int *track, int *index)
295 {
296 return wm_scsi2_get_drive_status(d, oldmode, mode, pos, track, index);
297 } /* gen_get_drive_status() */
298
299 /*
300 * Get the number of tracks on the CD.
301 */
302 int
gen_get_trackcount(struct wm_drive * d,int * tracks)303 gen_get_trackcount(struct wm_drive *d, int *tracks)
304 {
305 return wm_scsi2_get_trackcount(d, tracks);
306 } /* gen_get_trackcount() */
307
308 /*
309 * Get the start time and mode (data or audio) of a track.
310 */
311 int
gen_get_trackinfo(struct wm_drive * d,int track,int * data,int * startframe)312 gen_get_trackinfo(struct wm_drive *d, int track, int *data, int *startframe)
313 {
314 return wm_scsi2_get_trackinfo(d, track, data, startframe);
315 } /* gen_get_trackinfo() */
316
317 /*
318 * Get the number of frames on the CD.
319 */
320 int
gen_get_cdlen(struct wm_drive * d,int * frames)321 gen_get_cdlen(struct wm_drive *d, int *frames)
322 {
323 int tmp;
324
325 return wm_scsi2_get_cdlen(d, frames);
326 } /* gen_get_cdlen() */
327
328 /*
329 * Play the CD from one position to another (both in frames.)
330 */
331 int
gen_play(struct wm_drive * d,int start,int end)332 gen_play(struct wm_drive *d, int start, int end)
333 {
334 return wm_scsi2_play(d, start, end);
335 } /* gen_play() */
336
337 /*
338 * Pause the CD.
339 */
340 int
gen_pause(struct wm_drive * d)341 gen_pause(struct wm_drive *d)
342 {
343 return wm_scsi2_pause(d);
344 } /* gen_pause() */
345
346 /*
347 * Resume playing the CD (assuming it was paused.)
348 */
349 int
gen_resume(struct wm_drive * d)350 gen_resume(struct wm_drive *d)
351 {
352 return wm_scsi2_resume(d);
353 } /* gen_resume() */
354
355 /*
356 * Stop the CD.
357 */
358 int
gen_stop(struct wm_drive * d)359 gen_stop(struct wm_drive *d)
360 {
361 return wm_scsi2_stop(d);
362 } /* gen_stop() */
363
364
365 /*
366 * Eject the current CD, if there is one.
367 */
368 int
gen_eject(struct wm_drive * d)369 gen_eject(struct wm_drive *d)
370 {
371 return wm_scsi2_eject(d);
372 } /* gen_eject() */
373
374 /*
375 * Close the tray.
376 * please review scsi.c / wm_scsi2_closetray()
377 * and send changes to milliByte@DeathsDoor.com
378 */
379 int
gen_closetray(struct wm_drive * d)380 gen_closetray( struct wm_drive *d )
381 {
382 return wm_scsi2_closetray(d);
383 } /* gen_closetray() */
384
385
386 /*
387 * Set the volume level for the left and right channels. Their values
388 * range from 0 to 100.
389 */
390 int
gen_set_volume(struct wm_drive * d,int left,int right)391 gen_set_volume(struct wm_drive *d, int left, int right)
392 {
393 return wm_scsi2_set_volume(d, left, right);
394 } /* gen_set_volume() */
395
396 /*
397 * Read the initial volume from the drive, if available. Each channel
398 * ranges from 0 to 100, with -1 indicating data not available.
399 */
400 int
gen_get_volume(struct wm_drive * d,int * left,int * right)401 gen_get_volume(struct wm_drive *d, int *left, int *right)
402 {
403 return wm_scsi2_get_volume(d, left, right);
404 } /* gen_get_volume() */
405
406 #endif
407