1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
|
/* "hardware.c" copyright 1994 thomas insel
* copyrighy 1995 sven oliver moll */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <mntent.h>
#include <errno.h>
#ifdef sun
# include <sundev/srreg.h>
#elif defined linux
# include <linux/cdrom.h>
#else
# errror Please fix includes for your system in hardware.c
#endif
#include "config.h"
#include "database.h"
#include "hardware.h"
/* WWH hack to get rid of malloc/free's */
#ifdef CDCTRL
cdhw_t strHW;
#endif
extern int errno;
/************************************************************************/
/* Procedure: read_hw
* Purpose: to read hardware info
*
* Inputs: program name, CD file descriptor
* Outputs: to cdhw_t structure
* Returns: pointer to cdhw_t structure
* Notes:
* 1. The function free_hw_buf() must be called to free up the cdhw_t
* returned by this function. This function uses malloc to get
* a buffer (except when used with CDCTRL).
*/
/************************************************************************/
cdhw_t *
read_hw(char *progname, int cdfile, char *cdname)
{
int ii;
#ifdef CDCTRL
cdhw_t *hw = &strHW;
#else
cdhw_t *hw = malloc(sizeof(cdhw_t));
#endif
#ifdef DEBUG
fprintf (stderr, "read_hw: buffer=0x%lx\n", (long)((void *)hw));
#endif
/* WWH -- force all fields to 0 by default */
memset (hw, 0, sizeof(cdhw_t));
/* get status of CD-ROM */
hw->iStatus = cd_status(progname, cdfile, cdname, hw);
#ifdef DEBUG
fprintf (stderr, "read_hw: CD status=%s\n", cd_status_text(hw->iStatus));
#endif
/* if mounted or no CD, return extra error codes */
if (hw->iStatus == CD_STATUS_ERROR) {
#ifdef CDCTRL
hw->subchnl.cdsc_audiostatus = CDROM_AUDIO_ERROR;
return (hw);
#else
EXIT(1);
#endif
} else if ((hw->iStatus == CD_STATUS_NO_CD) ||
(hw->iStatus == CD_STATUS_REMOVED)) {
hw->subchnl.cdsc_audiostatus=NO_CDROM;
return hw;
}
else if (hw->iStatus == CD_STATUS_MOUNTED) {
hw->subchnl.cdsc_audiostatus=CDROM_MOUNTED;
return hw;
}
/* at this point, status must be IN or INSERTED */
/* read header */
/* if ( ioctl(cdfile, CDROMREADTOCHDR, &(hw->tochdr)) == -1 ) */
/* { */
/* fprintf(stderr, "%s: ioctl cdromreadtochdr\n", progname); */
/* #ifdef CDCTRL */
/* hw->subchnl.cdsc_audiostatus = CDROM_AUDIO_ERROR; */
/* return (hw); */
/* #else */
/* EXIT(1); */
/* #endif */
/* } */
/* printf ("Read TOCHDR\n"); */
/* read individual tracks */
hw->iData = hw->iAudio = 0;
for (ii=hw->tochdr.cdth_trk0-1; ii<=hw->tochdr.cdth_trk1; ii++) {
hw->tocentries[ii].cdte_track=
(ii==hw->tochdr.cdth_trk1) ? CDROM_LEADOUT : ii+1;
hw->tocentries[ii].cdte_format = CDROM_MSF;
if ( ioctl(cdfile, CDROMREADTOCENTRY, &(hw->tocentries[ii])) == -1 ) {
fprintf(stderr, "%s: ioctl cdromreadtocentry track %d\n",
progname, ii);
#ifdef CDCTRL
hw->subchnl.cdsc_audiostatus = CDROM_AUDIO_ERROR;
return (hw);
#else
EXIT(1);
#endif
}
/* determine if data or audio track, skip CDROM_LEADOUT */
if (ii!=hw->tochdr.cdth_trk1) {
if ((hw->tocentries[ii].cdte_ctrl&CDROM_DATA_TRACK) == 0)
hw->iAudio++;
else
hw->iData++;
}
}
/* if no audio tracks, i.e., all-data disc, set status to DATA_DISC */
if (hw->iAudio == 0) {
hw->iStatus = CD_STATUS_DATA_DISC;
hw->subchnl.cdsc_audiostatus = CDROM_DATA_DISC;
} else {
/* read subchannel info */
hw->subchnl.cdsc_format = CDROM_MSF;
if ( ioctl(cdfile, CDROMSUBCHNL, &(hw->subchnl)) == -1 ) {
fprintf(stderr, "%s: ioctl cdromsubchnl\n", progname);
#ifdef CDCTRL
hw->subchnl.cdsc_audiostatus = CDROM_AUDIO_ERROR;
return (hw);
#else
EXIT(1);
#endif
}
}
return hw;
}
/************************************************************************/
/* Procedure: checkmount
* Purpose: to check if this CD is mounted
*
* Inputs: name of program, name of CD-ROM
* Outputs: debug
* Returns: T/F
* Notes:
*/
/************************************************************************/
int checkmount(char *progname, char *pszName) {
FILE *fp;
struct mntent *mnt;
int ii;
char caB[100];
char *pszTest;
/* check pszName -- if NULL, return -1 */
if (pszName == NULL)
return (-1);
/* find out if the device is a link, resolve link name */
ii = readlink(pszName, caB, sizeof(caB)-1);
if (ii < 0) {
pszTest = pszName;
#ifdef DEBUG
fprintf (stderr, "chekmnt: %s not a link\n", pszName);
#endif
}else {
pszTest = &caB[0];
caB[ii] = '\0';
#ifdef DEBUG
fprintf (stderr, "chekmnt: link -> %s\n", caB);
#endif
}
/* check if drive is mounted (from Mark Buckaway's cdplayer code) */
if ((fp = setmntent (MOUNTED, "r")) == NULL) {
fprintf (stderr, "%s: Couldn't open %s: %s\n",
progname, MOUNTED, strerror (errno));
#ifdef CDCTRL
return (-1);
#else
EXIT(1);
#endif
}
while ((mnt = getmntent (fp)) != NULL) {
if (strstr (mnt->mnt_fsname, pszTest) != NULL) {
endmntent (fp);
return (TRUE);
}
}
endmntent (fp);
return (FALSE);
}
/************************************************************************/
/* Procedure: cd_status_text
* Purpose: to get status name in text
*
* Inputs: status code
* Outputs: to buffer
* Returns: pointer to status text string
* Notes:
* 1. Input values:
*
* 0 No CD in drive.
* 1 CD in drive.
* 2 CD has just been inserted (TOC has been read)
* 3 CD has just been removed
* 4 CD is mounted
*
*/
/************************************************************************/
char *cd_status_text (int iStatus)
{
char *pszResult;
switch (iStatus)
{
case CD_STATUS_ERROR:
pszResult = "error";
break;
case CD_STATUS_NO_CD:
pszResult = "no_disc";
break;
case CD_STATUS_CD_IN:
pszResult = "disc_in";
break;
case CD_STATUS_INSERTED:
pszResult = "inserted";
break;
case CD_STATUS_REMOVED:
pszResult = "removed";
break;
case CD_STATUS_MOUNTED:
pszResult = "mounted";
break;
case CD_STATUS_DATA_DISC:
pszResult = "data_disc";
break;
default:
pszResult = "unknown";
break;
}
return (pszResult);
}
/************************************************************************/
/* Procedure: cd_status
* Purpose: to get status of the CD-ROM
*
* Inputs: name of program (text)
* CD file descriptor (int), -1 if not open
* cdname (text) name or symlink to CD device
* pHW (cdhw_t) pointer to hardware descriptor block
* Outputs: debug info only
* Returns: see below
* Notes:
* 1. Stolen from XPlaycd code...
* 2. Return values:
*
* -N error code
* 0 No CD in drive.
* 1 CD in drive.
* 2 CD has just been inserted (TOC has been read)
* 3 CD has just been removed
* 4 CD is mounted
*
*/
/************************************************************************/
int cd_status(char *progname, int cd_fd, char *cdname, cdhw_t *pHw) {
/* struct cdrom_subchnl sc; */
/* struct cdrom_tochdr hdr; */
int iResult;
/* check if the CD-ROM is mounted, if so, return MOUNTED */
iResult = checkmount(progname, cdname);
if (iResult < 0)
return (iResult);
else if (iResult == TRUE)
return CD_STATUS_MOUNTED;
/* try to open the CD-ROM. If we fail, report error */
if (cd_fd < 0) {
if ((cd_fd = open(cdname, O_RDONLY | O_NONBLOCK)) < 0) {
if (errno == EACCES) {
fprintf(stderr, "%s error opening %s\n", progname, cdname);
fprintf(stderr,
"As root, please run\n\nadduser %s cdrom\n\n%s\n%s\n",
"<yourname>",
"to give yourself permission to access the CD-ROM device.",
"Also ensure the cdrom device belongs to the cdrom group.");
}
}
else if (errno==ENOENT) {
fprintf(stderr,"%s: can't open %s: ", progname, cdname);
perror("");
#ifdef CDCTRL
return (-1);
#else
EXIT(1);
#endif
}
else if (errno != ENXIO) {
return CD_STATUS_NO_CD;
}
}
/* get subchannel info, if invalid, no disc in drive */
pHw->subchnl.cdsc_format = CDROM_MSF;
if (ioctl(cd_fd, CDROMSUBCHNL, &pHw->subchnl)) {
/* cur_cdmode = 5; */
/* cur_track = -1; */
/* cur_cdlen = cur_tracklen = 1; */
/* cur_pos_abs = cur_pos_rel = cur_frame = 0; */
/* close(cd_fd); */
/* cd_fd = -1; */
/* #ifdef DBG_EXIT */
/* fprintf(stderr,"exit 2\n"); */
/* #endif */
return CD_STATUS_NO_CD;
}
/* read the header */
if (ioctl(cd_fd, CDROMREADTOCHDR, &pHw->tochdr))
return CD_STATUS_NO_CD;
switch (pHw->subchnl.cdsc_audiostatus) {
case CDROM_AUDIO_PLAY:
case CDROM_AUDIO_PAUSED:
case CDROM_AUDIO_COMPLETED:
return CD_STATUS_CD_IN;
break;
}
return CD_STATUS_CD_IN;
}
/************************************************************************/
/* Procedure: free_hw_buf
* Purpose: to free up hardware buffer returned by read_hw
*
* Inputs: pointer to buffer
* Outputs: debug info only
* Returns: n/a
* Notes:
* 1.
*/
/************************************************************************/
void free_hw_buf(cdhw_t *pHw)
{
#ifdef DEBUG
fprintf (stderr,"free_hw: bufp=0x%lx\n", (long)((char *)pHw));
#endif
#ifndef CDCTRL
if ((void *)pHw != NULL)
free ((void *)pHw);
#endif
}
|