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

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  * HP/UX-specific drive control routines.
0022  */
0023 
0024 #if defined(hpux) || defined(__hpux)
0025 
0026 #include <errno.h>
0027 #include <stdio.h>
0028 #include <fcntl.h>
0029 #include <ustat.h>
0030 #include <unistd.h>
0031 #include <sys/types.h>
0032 #include <sys/param.h>
0033 #include <sys/stat.h>
0034 
0035 #include "include/wm_config.h"
0036 
0037 /*
0038  * this is for glibc 2.x which the ust structure in
0039  * ustat.h not stat.h
0040  */
0041 #ifdef __GLIBC__
0042 #include <sys/ustat.h>
0043 #endif
0044 
0045 #include <sys/time.h>
0046 #include <sys/scsi.h>
0047 
0048 #include "include/wm_struct.h"
0049 #include "include/wm_helpers.h"
0050 #include "include/wm_cdtext.h"
0051 
0052 #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM
0053 
0054 void *malloc();
0055 char *strchr();
0056 
0057 int min_volume = 0;
0058 int max_volume = 255;
0059 
0060 /*--------------------------------------------------------*
0061  * Initialize the drive.  A no-op for the generic driver.
0062  *--------------------------------------------------------*/
0063 int
0064 gen_init( struct wm_drive *d )
0065 {
0066   return 0;
0067 } /* gen_init() */
0068 
0069 
0070 /*-------------------------------------------------------------*
0071  * Open the CD and figure out which kind of drive is attached.
0072  *-------------------------------------------------------------*/
0073 int
0074 gen_open( struct wm_drive *d )
0075 {
0076     int flag = 1;
0077 
0078     if (d->fd >= 0) {   /* Device already open? */
0079         wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "gen_open(): [device is open (fd=%d)]\n", d->fd);
0080         return 0;
0081     }
0082 
0083 
0084     d->fd = open(d->cd_device, O_RDWR);
0085     if (d->fd < 0) {
0086         if (errno == EACCES) {
0087             return -EACCES;
0088         } else if (errno != EINTR) {
0089             return -6;
0090         }
0091 
0092         /* No CD in drive. */
0093         return 1;
0094     }
0095 
0096     /* Prepare the device to receive raw SCSI commands. */
0097     if (ioctl(d->fd, SIOC_CMD_MODE, &flag) < 0) {
0098       fprintf(stderr, "%s: SIOC_CMD_MODE: true: %s\n",
0099           d->cd_device, strerror(errno));
0100       /*exit(1);*/
0101     }
0102 
0103   /* Default drive is the HP one, which might not respond to INQUIRY */
0104   strcpy(d->vendor, "TOSHIBA");
0105   strcpy(d->model, "XM-3301");
0106   d->rev[0] = '\0';
0107 
0108   return 0;
0109 } /* gen_open() */
0110 
0111 /*----------------------------------*
0112  * Send a SCSI command out the bus.
0113  *----------------------------------*/
0114 int
0115 gen_scsi( struct wm_drive *d, unsigned char *cdb, int cdblen,
0116      void *retbuf, int retbuflen, int getreply )
0117 {
0118 #ifdef SIOC_IO
0119     struct sctl_io cmd;
0120 
0121     memset(&cmd, 0, sizeof(cmd));
0122     cmd.cdb_length = cdblen;
0123     cmd.data = retbuf;
0124     cmd.data_length = retbuflen;
0125     cmd.max_msecs = 1000;
0126     cmd.flags = getreply ? SCTL_READ : 0;
0127     memcpy(cmd.cdb, cdb, cdblen);
0128 
0129     return ioctl(d->fd, SIOC_IO, &cmd);
0130 #else
0131     /* this code, for pre-9.0, is BROKEN!  ugh. */
0132     char reply_buf[12];
0133     struct scsi_cmd_parms cmd;
0134 
0135     memset(&cmd, 0, sizeof(cmd));
0136     cmd.clock_ticks = 500;
0137     cmd.cmd_mode = 1;
0138     cmd.cmd_type = cdblen;
0139     memcpy(cmd.command, cdb, cdblen);
0140     if (ioctl(d->fd, SIOC_SET_CMD, &cmd) < 0)
0141         return -1;
0142 
0143     if (! retbuf || ! retbuflen)
0144         read(d->fd, reply_buf, sizeof(reply_buf));
0145     else if (getreply) {
0146         if (read(d->fd, retbuf, retbuflen) < 0)
0147             return -1;
0148     } else if (write(d->fd, retbuf, retbuflen) < 0)
0149         return -1;
0150 
0151     return 0;
0152 #endif
0153 } /* gen_scsi() */
0154 
0155 int
0156 gen_close( struct wm_drive *d )
0157 {
0158     if(d->fd != -1) {
0159         wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closing the device\n");
0160         close(d->fd);
0161         d->fd = -1;
0162     }
0163     return 0;
0164 }
0165 
0166 /*--------------------------------------------------------------------------*
0167  * Get the current status of the drive: the current play mode, the absolute
0168  * position from start of disc (in frames), and the current track and index
0169  * numbers if the CD is playing or paused.
0170  *--------------------------------------------------------------------------*/
0171 int
0172 gen_get_drive_status( struct wm_drive *d, int oldmode, int *mode,
0173                       int *pos, int *track, int *index )
0174 {
0175     return wm_scsi2_get_drive_status(d, oldmode, mode, pos, track, index);
0176 } /* gen_get_drive_status() */
0177 
0178 /*-------------------------------------*
0179  * Get the number of tracks on the CD.
0180  *-------------------------------------*/
0181 int
0182 gen_get_trackcount(struct wm_drive *d, int *tracks )
0183 {
0184     return wm_scsi2_get_trackcount(d, tracks);
0185 } /* gen_get_trackcount() */
0186 
0187 /*---------------------------------------------------------*
0188  * Get the start time and mode (data or audio) of a track.
0189  *---------------------------------------------------------*/
0190 int
0191 gen_get_trackinfo( struct wm_drive *d, int *track, int *data, int *startframe)
0192 {
0193     return wm_scsi2_get_trackinfo(d, track, data, startframe);
0194 } /* gen_get_trackinfo() */
0195 
0196 /*-------------------------------------*
0197  * Get the number of frames on the CD.
0198  *-------------------------------------*/
0199 int gen_get_cdlen(struct wm_drive *d, int *frames)
0200 {
0201     return wm_scsi2_get_cdlen(d, frames);
0202 } /* gen_get_cdlen() */
0203 
0204 /*------------------------------------------------------------*
0205  * Play the CD from one position to another (both in frames.)
0206  *------------------------------------------------------------*/
0207 int
0208 gen_play( struct wm_drive *d, int start, int end )
0209 {
0210     return wm_scsi2_play(d, start, end);
0211 } /* gen_play() */
0212 
0213 /*---------------*
0214  * Pause the CD.
0215  *---------------*/
0216 int
0217 gen_pause( struct wm_drive *d )
0218 {
0219     return wm_scsi2_pause(d);
0220 } /* gen_pause() */
0221 
0222 /*-------------------------------------------------*
0223  * Resume playing the CD (assuming it was paused.)
0224  *-------------------------------------------------*/
0225 int
0226 gen_resume( struct wm_drive *d )
0227 {
0228     return wm_scsi2_resume(d);
0229 } /* gen_resume() */
0230 
0231 /*--------------*
0232  * Stop the CD.
0233  *--------------*/
0234 int
0235 gen_stop( struct wm_drive *d )
0236 {
0237     return wm_scsi2_stop(d);
0238 } /* gen_stop() */
0239 
0240 
0241 /*----------------------------------------*
0242  * Eject the current CD, if there is one.
0243  *----------------------------------------*/
0244 int
0245 gen_eject( struct wm_drive *d )
0246 {
0247     struct stat stbuf;
0248     struct ustat ust;
0249 
0250     if (fstat(d->fd, &stbuf) != 0)
0251         return -2;
0252 
0253     /* Is this a mounted filesystem? */
0254     if (ustat(stbuf.st_rdev, &ust) == 0)
0255         return -3;
0256 
0257     return wm_scsi2_eject(d);
0258 } /* gen_eject() */
0259 
0260 /*----------------------------------------*
0261  * Close the CD tray
0262  *----------------------------------------*/
0263 int
0264 gen_closetray(struct wm_drive *d)
0265 {
0266     return wm_scsi2_closetray(d);
0267 } /* gen_closetray() */
0268 
0269 
0270 /*---------------------------------------------------------------------*
0271  * Set the volume level for the left and right channels.  Their values
0272  * range from 0 to 100.
0273  *---------------------------------------------------------------------*/
0274 int
0275 gen_set_volume( struct wm_drive *d, int left, int right )
0276 {
0277     return wm_scsi2_set_volume(d, left, right);
0278 } /* gen_set_volume() */
0279 
0280 /*---------------------------------------------------------------------*
0281  * Read the initial volume from the drive, if available.  Each channel
0282  * ranges from 0 to 100, with -1 indicating data not available.
0283  *---------------------------------------------------------------------*/
0284 int
0285 gen_get_volume( struct wm_drive *d, int *left, int *right )
0286 {
0287     return wm_scsi2_get_volume(d, left, right);
0288 } /* gen_get_volume() */
0289 
0290 #endif
0291 
0292