File indexing completed on 2024-04-28 08:46:55
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 * SCO Openserver R5 specific. Derived from the KSCD plat_scor5.c 0022 * 0023 */ 0024 0025 #if defined(M_UNIX) || defined(__M_UNIX) 0026 0027 #include "include/wm_config.h" 0028 0029 #include <sys/types.h> 0030 #include <stdio.h> 0031 #include <ctype.h> 0032 #include <string.h> 0033 #include <fcntl.h> 0034 #include <stdlib.h> 0035 #include <unistd.h> 0036 #include <signal.h> 0037 #include <sys/stat.h> 0038 #include <sys/scsi.h> 0039 #include <sys/scsicmd.h> 0040 #include <errno.h> 0041 #include <macros.h> 0042 0043 #include "include/wm_struct.h" 0044 #include "include/gen_scsi.h" 0045 #include "include/wm_cdtext.h" 0046 0047 #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM 0048 0049 #define SENSE_SZ EXTD_SENSE_LEN 0050 0051 void *malloc(); 0052 char *strchr(); 0053 0054 int min_volume = 0; 0055 int max_volume = 255; 0056 0057 /* 0058 * platformspecific internal function 0059 */ 0060 static int 0061 create_cdrom_node(char *dev_name) 0062 { 0063 char pass_through[100]; 0064 int file_des; 0065 struct stat sbuf; 0066 int err; 0067 int ccode; 0068 0069 0070 strncpy(pass_through, dev_name, sizeof(pass_through)-2); 0071 pass_through[sizeof(pass_through) - 2] = '\0'; 0072 strcat(pass_through, "p" ); 0073 0074 if (setreuid(-1,0) < 0) 0075 { 0076 perror("setregid/setreuid/access"); 0077 return -1; 0078 } 0079 0080 ccode = access(pass_through, F_OK); 0081 0082 if (ccode < 0) 0083 { 0084 0085 if (stat(dev_name, &sbuf) < 0) 0086 { 0087 perror("Call to get pass-through device number failed"); 0088 return -1; 0089 } 0090 0091 if (mknod(pass_through, (S_IFCHR | S_IREAD | S_IWRITE), 0092 sbuf.st_rdev) < 0) 0093 { 0094 perror("Unable to make pass-through node"); 0095 return -1; 0096 } 0097 0098 if (chown(pass_through, 0 , 0) < 0) 0099 { 0100 perror("chown"); 0101 return -1; 0102 } 0103 0104 if (chmod(pass_through, 0660 ) < 0) 0105 { 0106 perror("chmod"); 0107 return -1; 0108 } 0109 } 0110 0111 file_des = open( pass_through, O_RDONLY); 0112 err = errno; 0113 0114 /* 0115 if ( (setreuid(-1,getuid()) < 0) || (setregid(-1,getgid()) < 0) ) 0116 { 0117 perror("setreuid/setregid"); 0118 exit(1); 0119 } 0120 0121 */ 0122 0123 errno = err; 0124 return file_des; 0125 } /* create_cdrom_node() */ 0126 0127 0128 /* 0129 * Initialize the drive. A no-op for the generic driver. 0130 */ 0131 int 0132 gen_init(struct wm_drive *d) 0133 { 0134 return (0); 0135 } /* gen_init() */ 0136 0137 /* 0138 * Open the CD and figure out which kind of drive is attached. 0139 */ 0140 int 0141 gen_open(struct wm_drive *d) 0142 { 0143 if (d->fd > -1) { /* Device already open? */ 0144 wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "gen_open(): [device is open (fd=%d)]\n", d->fd); 0145 return 0; 0146 } 0147 0148 d->fd = create_cdrom_node(d->cd_device); /* this will do open */ 0149 if (d->fd < 0) { 0150 if (errno == EACCES) { 0151 } else if (errno != EINTR) { 0152 perror(d->cd_device); 0153 return -6; 0154 } 0155 0156 /* cannot access CDROM device */ 0157 return -1; 0158 } 0159 0160 return 0; 0161 } /* gen_open */ 0162 0163 /* 0164 * Send a SCSI command out the bus. 0165 */ 0166 int 0167 gen_scsi(struct wm_drive *d, unsigned char *xcdb, int cdblen, 0168 char *retbuf, int retbuflen, int getreply) 0169 { 0170 int ccode; 0171 int file_des = d->fd; 0172 unsigned char sense_buffer[ SENSE_SZ ]; 0173 0174 /* getreply == 1 is read, == 0 is write */ 0175 0176 struct scsicmd2 sb; /* Use command with automatic sense */ 0177 0178 if (cdblen > SCSICMDLEN) 0179 { 0180 fprintf(stderr,"Cannot handle longer commands than %d bytes.\n", SCSICMDLEN); 0181 exit(-1); 0182 } 0183 0184 /* Get the command */ 0185 memcpy(sb.cmd.cdb, xcdb, cdblen); 0186 sb.cmd.cdb_len = cdblen; 0187 0188 /* Point to data buffer */ 0189 sb.cmd.data_ptr = retbuf; 0190 sb.cmd.data_len = retbuflen; 0191 0192 /* Is this write or read ? */ 0193 sb.cmd.is_write = (getreply==1) ? 0 : 1; 0194 0195 /* Zero out return status fields */ 0196 sb.cmd.host_sts = 0; 0197 sb.cmd.target_sts = 0; 0198 0199 /* Set up for possible sense info */ 0200 0201 sb.sense_ptr = sense_buffer; 0202 sb.sense_len = sizeof(sense_buffer); 0203 0204 ccode = ioctl(file_des, SCSIUSERCMD2, &sb); 0205 0206 if ( sb.cmd.target_sts != 02 ) 0207 return ccode; 0208 0209 return 0; 0210 } /* gen_scsi() */ 0211 0212 int 0213 gen_close( struct wm_drive *d ) 0214 { 0215 if(d->fd != -1) { 0216 wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closing the device\n"); 0217 close(d->fd); 0218 d->fd = -1; 0219 } 0220 return 0; 0221 } 0222 0223 void 0224 keep_cd_open() { } 0225 0226 /* 0227 * Get the current status of the drive: the current play mode, the absolute 0228 * position from start of disc (in frames), and the current track and index 0229 * numbers if the CD is playing or paused. 0230 */ 0231 int 0232 gen_get_drive_status(wm_drive *d, int oldmode, int *mode, 0233 int *pos, int *track, int *index) 0234 { 0235 return (wm_scsi2_get_drive_status(d, oldmode, mode, pos, track, index)); 0236 } /* gen_get_drive_status() */ 0237 0238 /* 0239 * Get the number of tracks on the CD. 0240 */ 0241 int 0242 gen_get_trackcount(struct wm_drive *d, int *tracks) 0243 { 0244 return (wm_scsi2_get_trackcount(d, tracks)); 0245 } /* gen_get_trackcount() */ 0246 0247 0248 /* 0249 * Get the start time and mode (data or audio) of a track. 0250 */ 0251 int 0252 gen_get_trackinfo(struct wm_drive *d, int track, int *data, int *startframe) 0253 { 0254 return (wm_scsi2_get_trackinfo(d, track, data, startframe)); 0255 } /* gen_get_trackinfo() */ 0256 0257 /* 0258 * Get the number of frames on the CD. 0259 */ 0260 int 0261 gen_get_cdlen(struct wm_drive *d, int *frames) 0262 { 0263 return (wm_scsi2_get_cdlen(d, frames)); 0264 } /* gen_get_cdlen() */ 0265 0266 0267 /* 0268 * Play the CD from one position to another (both in frames.) 0269 */ 0270 int 0271 gen_play(struct wm_drive *d, int start, int end) 0272 { 0273 return (wm_scsi2_play(d, start, end)); 0274 } /* gen_play() */ 0275 0276 /* 0277 * Pause the CD. 0278 */ 0279 int 0280 gen_pause( struct wm_drive *d ) 0281 { 0282 return (wm_scsi2_pause(d)); 0283 } /* gen_pause() */ 0284 0285 /* 0286 * Resume playing the CD (assuming it was paused.) 0287 */ 0288 int 0289 gen_resume( struct wm_drive *d ) 0290 { 0291 return (wm_scsi2_resume(d)); 0292 } /* gen_resume() */ 0293 0294 /* 0295 * Stop the CD. 0296 */ 0297 int 0298 gen_stop(struct wm_drive *d) 0299 { 0300 return (wm_scsi2_stop(d)); 0301 } /* gen_stop() */ 0302 0303 /* 0304 * Eject the current CD, if there is one. 0305 */ 0306 int 0307 gen_eject(struct wm_drive *d) 0308 { 0309 int stat; 0310 0311 stat = wm_scsi2_eject(d); 0312 wm_susleep(1000); 0313 return (stat); 0314 } /* gen_eject() */ 0315 0316 0317 int 0318 gen_closetray(struct wm_drive *d) 0319 { 0320 return(wm_scsi2_closetray(d)); 0321 } /* gen_closetray() */ 0322 0323 0324 /* 0325 * Set the volume level for the left and right channels. Their values 0326 * range from 0 to 100. 0327 */ 0328 int 0329 gen_set_volume(struct wm_drive *d, int left, int right) 0330 { 0331 return (wm_scsi2_set_volume(d, left, right)); 0332 } /* gen_set_volume() */ 0333 0334 /* 0335 * Read the initial volume from the drive, if available. Each channel 0336 * ranges from 0 to 100, with -1 indicating data not available. 0337 */ 0338 int 0339 gen_get_volume(struct wm_drive *d, int *left, int *right) 0340 { 0341 return (wm_scsi2_get_volume(d, left, right)); 0342 } /* gen_get_volume() */ 0343 0344 #endif /* M_UNIX */ 0345 0346 0347 0348