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