File indexing completed on 2024-04-21 04:54:23

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