File indexing completed on 2024-04-21 04:54:24
0001 /* 0002 * This file is part of WorkMan, the civilized CD player library 0003 * Copyright (C) 1991-1997 by Steven Grimm <koreth@midwinter.com> 0004 * Copyright (C) by Dirk Försterling <milliByte@DeathsDoor.com> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public 0017 * License along with this library; if not, write to the Free 0018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0019 * 0020 * 0021 * SVR4 specific. Much of this is similar to plat_hpux.c. 0022 */ 0023 0024 #if (defined(SVR4) || defined(__SVR4)) && !defined(sun) && !defined(__sun) && !defined(sony_news) && !defined(__sony_news) 0025 0026 0027 #include <sys/types.h> 0028 #include <stdio.h> 0029 #include <ctype.h> 0030 #include <string.h> 0031 #include <fcntl.h> 0032 #include <stdlib.h> 0033 #include <unistd.h> 0034 #include <signal.h> 0035 #include <sys/mkdev.h> 0036 #include <sys/stat.h> 0037 #include <sys/sdi.h> 0038 #include <sys/sdi_edt.h> 0039 #include <sys/scsi.h> 0040 #include <errno.h> 0041 0042 #include "include/wm_config.h" 0043 #include "include/wm_struct.h" 0044 #include "include/wm_cdtext.h" 0045 0046 #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM 0047 0048 0049 void *malloc(); 0050 char *strchr(); 0051 0052 int min_volume = 0; 0053 int max_volume = 255; 0054 0055 static int 0056 create_cdrom_node(char *dev_name) 0057 { 0058 char pass_through[100]; 0059 int file_des; 0060 dev_t pass_thru_device; 0061 int err; 0062 int ccode; 0063 0064 0065 strncpy(pass_through, dev_name, sizeof(pass_through) - 2); 0066 pass_through[sizeof(pass_through) - 2] = '\0'; 0067 strcat(pass_through, "p" ); 0068 0069 if (setreuid(-1,0) < 0) 0070 { 0071 perror("setregid/setreuid/access"); 0072 return -1; 0073 } 0074 0075 ccode = access(pass_through, F_OK); 0076 0077 if (ccode < 0) 0078 { 0079 if ((file_des = open(dev_name, O_RDONLY)) < 0) 0080 { 0081 perror("open cdrom devices failed"); 0082 return -1; 0083 } 0084 0085 if (ioctl(file_des, B_GETDEV, &pass_thru_device) < 0) 0086 { 0087 perror("Call to get pass-through device number failed"); 0088 return -1; 0089 } 0090 0091 (void)close(file_des); 0092 0093 if (mknod(pass_through, (S_IFCHR | S_IREAD | S_IWRITE), 0094 pass_thru_device) < 0) 0095 { 0096 perror("Unable to make pass-through node"); 0097 return -1; 0098 } 0099 0100 if (chown(pass_through, 0 , 0) < 0) 0101 { 0102 perror("chown"); 0103 return -1; 0104 } 0105 0106 if (chmod(pass_through, 0660 ) < 0) 0107 { 0108 perror("chmod"); 0109 return -1; 0110 } 0111 } 0112 0113 file_des = open( pass_through, O_RDWR); 0114 err = errno; 0115 0116 if ( (setreuid(-1,getuid()) < 0) || (setregid(-1,getgid()) < 0) ) 0117 { 0118 perror("setreuid/setregid"); 0119 return -1; 0120 } 0121 errno = err; 0122 return file_des; 0123 } /* create_cdrom_node() */ 0124 0125 const char* 0126 find_cdrom() 0127 { 0128 /* 0129 ** the path of the device has to start w/ /dev 0130 ** otherwise we are vulnerable to race conditions 0131 ** Thomas Biege <thomas@suse.de> 0132 */ 0133 const char* device = NULL; 0134 0135 device = getenv("CDROM"); 0136 if ( (device != NULL) && 0137 !(strncmp("/dev/", device, 5) || 0138 strstr(_device, "/../") )) 0139 return device; 0140 0141 if (access("/dev/cdrom/cdrom1", F_OK) == 0) 0142 { 0143 return "/dev/cdrom/cdrom1"; 0144 } 0145 else if (access("/dev/cdrom/cdrom2", F_OK) == 0) 0146 { 0147 return "/dev/cdrom/cdrom2"; 0148 } 0149 else 0150 { 0151 fprintf(stderr, "Could not find a CD device!\n"); 0152 return NULL; 0153 } 0154 } /* find_cdrom() */ 0155 0156 /* 0157 * Initialize the drive. A no-op for the generic driver. 0158 */ 0159 int 0160 gen_init(struct wm_drive *d) 0161 { 0162 return 0; 0163 } /* gen_init() */ 0164 0165 /* 0166 * Open the CD and figure out which kind of drive is attached. 0167 */ 0168 int 0169 gen_open(struct wm_drive *d) 0170 { 0171 if (d->fd >= 0) { /* Device already open? */ 0172 wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "gen_open(): [device is open (fd=%d)]\n", d->fd); 0173 return 0; 0174 } 0175 0176 d->fd = create_cdrom_node(d->cd_device); /* this will do open */ 0177 if (d->fd < 0) { 0178 if (errno == EACCES) 0179 else if (errno != EINTR) 0180 return -6; 0181 0182 /* No CD in drive. (Is this true also for svr4 ? XXX ) */ 0183 return 1; 0184 } 0185 0186 return 0; 0187 } /* gen_open() */ 0188 0189 /* 0190 * Send a SCSI command out the bus. 0191 */ 0192 int 0193 gen_scsi( struct wm_drive *d, unsigned char *xcdb, int cdblen, 0194 char *retbuf, int retbuflen, int getreply) 0195 { 0196 int ccode; 0197 int file_des = d->fd; 0198 int i,j; 0199 unsigned char sense_buffer[ SENSE_SZ ]; 0200 int errno_save; 0201 0202 /* getreply == 1 is read, == 0 is write */ 0203 0204 struct sb sb; 0205 struct scs scs; 0206 0207 sb.sb_type = ISCB_TYPE; 0208 0209 sb.SCB.sc_comp_code = SDI_PROGRES; 0210 sb.SCB.sc_int = NULL; 0211 sb.SCB.sc_wd = 0; 0212 sb.SCB.sc_dev.sa_major = 0; 0213 sb.SCB.sc_dev.sa_minor = 0; 0214 sb.SCB.sc_dev.sa_lun = 0; 0215 sb.SCB.sc_dev.sa_exlun = 0; 0216 sb.SCB.sc_status = 0; 0217 sb.SCB.sc_link = (struct sb *) NULL; 0218 sb.SCB.sc_resid = 0; 0219 0220 sb.SCB.sc_cmdpt = (void *)xcdb; 0221 sb.SCB.sc_cmdsz = cdblen; 0222 0223 sb.SCB.sc_datapt = retbuf ; 0224 sb.SCB.sc_datasz = retbuflen ; 0225 0226 if (getreply == 1) 0227 sb.SCB.sc_mode = SCB_READ; 0228 else 0229 sb.SCB.sc_mode = SCB_WRITE; 0230 0231 sb.SCB.sc_time = 500; 0232 0233 ccode = ioctl(file_des, SDI_SEND, &sb); 0234 0235 if ( (sb.SCB.sc_comp_code != 0xd000000e ) || 0236 ( sb.SCB.sc_status != 02) ) 0237 return ccode; 0238 0239 errno_save = errno; 0240 0241 sb.SCB.sc_comp_code = SDI_PROGRES; 0242 sb.SCB.sc_int = NULL; 0243 sb.SCB.sc_wd = 0; 0244 sb.SCB.sc_dev.sa_major = 0; 0245 sb.SCB.sc_dev.sa_minor = 0; 0246 sb.SCB.sc_dev.sa_lun = 0; 0247 sb.SCB.sc_dev.sa_exlun = 0; 0248 sb.SCB.sc_status = 0; 0249 sb.SCB.sc_link = (struct sb *) NULL; 0250 sb.SCB.sc_resid = 0; 0251 0252 scs.ss_op = SS_REQSEN; 0253 scs.ss_lun = 0; 0254 scs.ss_addr1 = 0; 0255 scs.ss_addr = 0; 0256 scs.ss_len = SENSE_SZ; 0257 scs.ss_cont = 0; 0258 0259 sb.SCB.sc_cmdpt = SCS_AD(&scs); 0260 sb.SCB.sc_cmdsz = SCS_SZ; 0261 sb.SCB.sc_datapt = sense_buffer; 0262 sb.SCB.sc_datasz = 18; 0263 sb.SCB.sc_mode = SCB_READ; 0264 sb.SCB.sc_time = 5000; 0265 0266 if (ioctl(file_des, SDI_SEND, &sb) < 0) 0267 { 0268 fprintf(stderr,"Cannot read sense.\n"); 0269 exit(-1); 0270 } 0271 0272 errno=errno_save; 0273 return -1; 0274 } /* gen_scsi() */ 0275 0276 int 0277 gen_close( struct wm_drive *d ) 0278 { 0279 if(d->fd != -1) { 0280 wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closing the device\n"); 0281 close(d->fd); 0282 d->fd = -1; 0283 } 0284 return 0; 0285 } 0286 0287 /* 0288 * Get the current status of the drive: the current play mode, the absolute 0289 * position from start of disc (in frames), and the current track and index 0290 * numbers if the CD is playing or paused. 0291 */ 0292 int 0293 gen_get_drive_status(struct wm_drive *d, int oldmode, 0294 int *mode, int *pos, int *track, int *index) 0295 { 0296 return wm_scsi2_get_drive_status(d, oldmode, mode, pos, track, index); 0297 } /* gen_get_drive_status() */ 0298 0299 /* 0300 * Get the number of tracks on the CD. 0301 */ 0302 int 0303 gen_get_trackcount(struct wm_drive *d, int *tracks) 0304 { 0305 return wm_scsi2_get_trackcount(d, tracks); 0306 } /* gen_get_trackcount() */ 0307 0308 /* 0309 * Get the start time and mode (data or audio) of a track. 0310 */ 0311 int 0312 gen_get_trackinfo(struct wm_drive *d, int track, int *data, int *startframe) 0313 { 0314 return wm_scsi2_get_trackinfo(d, track, data, startframe); 0315 } /* gen_get_trackinfo() */ 0316 0317 /* 0318 * Get the number of frames on the CD. 0319 */ 0320 int 0321 gen_get_cdlen(struct wm_drive *d, int *frames) 0322 { 0323 int tmp; 0324 0325 return wm_scsi2_get_cdlen(d, frames); 0326 } /* gen_get_cdlen() */ 0327 0328 /* 0329 * Play the CD from one position to another (both in frames.) 0330 */ 0331 int 0332 gen_play(struct wm_drive *d, int start, int end) 0333 { 0334 return wm_scsi2_play(d, start, end); 0335 } /* gen_play() */ 0336 0337 /* 0338 * Pause the CD. 0339 */ 0340 int 0341 gen_pause(struct wm_drive *d) 0342 { 0343 return wm_scsi2_pause(d); 0344 } /* gen_pause() */ 0345 0346 /* 0347 * Resume playing the CD (assuming it was paused.) 0348 */ 0349 int 0350 gen_resume(struct wm_drive *d) 0351 { 0352 return wm_scsi2_resume(d); 0353 } /* gen_resume() */ 0354 0355 /* 0356 * Stop the CD. 0357 */ 0358 int 0359 gen_stop(struct wm_drive *d) 0360 { 0361 return wm_scsi2_stop(d); 0362 } /* gen_stop() */ 0363 0364 0365 /* 0366 * Eject the current CD, if there is one. 0367 */ 0368 int 0369 gen_eject(struct wm_drive *d) 0370 { 0371 return wm_scsi2_eject(d); 0372 } /* gen_eject() */ 0373 0374 /* 0375 * Close the tray. 0376 * please review scsi.c / wm_scsi2_closetray() 0377 * and send changes to milliByte@DeathsDoor.com 0378 */ 0379 int 0380 gen_closetray( struct wm_drive *d ) 0381 { 0382 return wm_scsi2_closetray(d); 0383 } /* gen_closetray() */ 0384 0385 0386 /* 0387 * Set the volume level for the left and right channels. Their values 0388 * range from 0 to 100. 0389 */ 0390 int 0391 gen_set_volume(struct wm_drive *d, int left, int right) 0392 { 0393 return wm_scsi2_set_volume(d, left, right); 0394 } /* gen_set_volume() */ 0395 0396 /* 0397 * Read the initial volume from the drive, if available. Each channel 0398 * ranges from 0 to 100, with -1 indicating data not available. 0399 */ 0400 int 0401 gen_get_volume(struct wm_drive *d, int *left, int *right) 0402 { 0403 return wm_scsi2_get_volume(d, left, right); 0404 } /* gen_get_volume() */ 0405 0406 #endif