~ubuntu-branches/ubuntu/hoary/kdemultimedia/hoary

« back to all changes in this revision

Viewing changes to kscd/libwm/plat_openbsd.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-01-22 15:00:51 UTC
  • Revision ID: james.westby@ubuntu.com-20030122150051-uihwkdoxf15mi1tn
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: plat_openbsd.c,v 1.7 2001/04/10 17:34:52 dfoerste Exp $
 
3
 *
 
4
 * This file is part of WorkMan, the civilized CD player library
 
5
 * (c) 1991-1997 by Steven Grimm (original author)
 
6
 * (c) by Dirk Fļæ½rsterling (current 'author' = maintainer)
 
7
 * The maintainer can be contacted by his e-mail address:
 
8
 * milliByte@DeathsDoor.com 
 
9
 *
 
10
 * This library is free software; you can redistribute it and/or
 
11
 * modify it under the terms of the GNU Library General Public
 
12
 * License as published by the Free Software Foundation; either
 
13
 * version 2 of the License, or (at your option) any later version.
 
14
 *
 
15
 * This library is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
 * Library General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU Library General Public
 
21
 * License along with this library; if not, write to the Free
 
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
23
 *
 
24
 *        
 
25
 * OpenBSD-specific drive control routines. (Based on plat_freebsd.c)
 
26
 *
 
27
 * Michael Shalayeff, 7/24/96
 
28
 * Todd Pfaff, 3/20/94
 
29
 *
 
30
 */
 
31
 
 
32
static char plat_openbsd[] = "$Id: plat_openbsd.c,v 1.7 2001/04/10 17:34:52 dfoerste Exp $";
 
33
 
 
34
#if defined(__OpenBSD__) || defined(__OpenBSD)
 
35
 
 
36
 
 
37
#include <errno.h>
 
38
#include <stdio.h>
 
39
#include <sys/types.h>
 
40
#include <sys/param.h>
 
41
#include <sys/mount.h>
 
42
#include <fcntl.h>
 
43
#include <sys/param.h>
 
44
#include <sys/stat.h>
 
45
 
 
46
#include "include/wm_config.h"
 
47
 
 
48
/* this is for glibc 2.x which defines the ust structure in ustat.h not stat.h */
 
49
#ifdef __GLIBC__
 
50
#include <sys/ustat.h>
 
51
#endif
 
52
 
 
53
#include <sys/time.h>
 
54
#include <string.h>
 
55
#include <sys/ioctl.h>
 
56
#include <sys/cdio.h>
 
57
#include <sys/scsiio.h>
 
58
#include <scsi/scsi_all.h>
 
59
#include <scsi/scsi_cd.h>
 
60
 
 
61
#include "include/wm_struct.h"
 
62
#include "include/wm_cdtext.h"
 
63
 
 
64
#define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM
 
65
 
 
66
void *malloc();
 
67
 
 
68
int     min_volume = 10;
 
69
int     max_volume = 255;
 
70
 
 
71
extern char     *cd_device;
 
72
 
 
73
 
 
74
/*
 
75
 * Initialize the drive.  A no-op for the generic driver.
 
76
 */
 
77
int
 
78
gen_init(struct wm_drive *d)
 
79
{
 
80
  return (0);
 
81
} /* gen_init() */
 
82
 
 
83
 
 
84
/*
 
85
 * Open the CD device and figure out what kind of drive is attached.
 
86
 */
 
87
int
 
88
wmcd_open(struct wm_drive *d)
 
89
{
 
90
  int           fd;
 
91
  static int    warned = 0;
 
92
  char vendor[32] = WM_STR_GENVENDOR;
 
93
  char  model[32] = WM_STR_GENMODEL;
 
94
  char    rev[32] = WM_STR_GENREV;
 
95
  
 
96
  if (d->fd >= 0)               /* Device already open? */
 
97
    {
 
98
       wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_open(): [device is open (fd=%d)]\n", d->fd);
 
99
       return (0);
 
100
    }
 
101
  
 
102
  if (cd_device == NULL)
 
103
    cd_device = DEFAULT_CD_DEVICE;
 
104
  
 
105
  d->fd = open(cd_device, 0);
 
106
  if (d->fd < 0)
 
107
    {
 
108
      if (errno == EACCES)
 
109
        {
 
110
          return -EACCES;
 
111
        }
 
112
      
 
113
      /* No CD in drive. */
 
114
      return (1);
 
115
    }
 
116
  
 
117
  /* Now fill in the relevant parts of the wm_drive structure. */
 
118
  fd = d->fd;
 
119
  
 
120
  *d = *(find_drive_struct(vendor, model, rev));
 
121
  wm_drive_settype(vendor, model, rev);
 
122
  
 
123
  (d->init)(d);
 
124
  
 
125
  d->fd = fd;
 
126
  
 
127
  return (0);
 
128
} /* wmcd_open() */
 
129
 
 
130
/*
 
131
 * Re-Open the device if it is open.
 
132
 */
 
133
int
 
134
wmcd_reopen( struct wm_drive *d )
 
135
{
 
136
  int status;
 
137
  
 
138
  do {
 
139
    wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "wmcd_reopen\n");
 
140
    if (d->fd >= 0)             /* Device really open? */
 
141
      {
 
142
        wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closing the device\n");
 
143
        status = close( d->fd );   /* close it! */
 
144
        /* we know, that the file is closed, do we? */
 
145
        d->fd = -1;
 
146
      }
 
147
    wm_susleep( 1000 );
 
148
    wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "calling wmcd_open()\n");
 
149
    status = wmcd_open( d ); /* open it as usual */
 
150
    wm_susleep( 1000 );
 
151
  } while ( status != 0 );
 
152
  return status;
 
153
} /* wmcd_reopen() */
 
154
 
 
155
/*
 
156
 * Send an arbitrary SCSI command to a device.
 
157
 *
 
158
 */
 
159
int
 
160
wm_scsi(struct wm_drive *d, unsigned char *cdb,
 
161
        int cdblen, void *retbuf, int retbuflen, int getreply)
 
162
{
 
163
  return (-1);
 
164
} /* wm_scsi() */
 
165
 
 
166
/*
 
167
 * Get the current status of the drive: the current play mode, the absolute
 
168
 * position from start of disc (in frames), and the current track and index
 
169
 * numbers if the CD is playing or paused.
 
170
 */
 
171
int
 
172
gen_get_drive_status(struct wm_drive *d, enum wm_cd_modes oldmode,
 
173
                     enum wm_cd_modes *mode, int *pos, int *track, int *index)
 
174
{
 
175
  struct ioc_read_subchannel    sc;
 
176
  struct cd_sub_channel_info    scd;
 
177
  
 
178
  /* If we can't get status, the CD is ejected, so default to that. */
 
179
  *mode = WM_CDM_EJECTED;
 
180
  
 
181
  sc.address_format     = CD_MSF_FORMAT;
 
182
  sc.data_format        = CD_CURRENT_POSITION;
 
183
  sc.track              = 0;
 
184
  sc.data_len           = sizeof(scd);
 
185
  sc.data               = (struct cd_sub_channel_info *)&scd;
 
186
  
 
187
  /* Is the device open? */
 
188
  if (d->fd < 0)
 
189
    {
 
190
      switch (wmcd_open(d)) {
 
191
      case -1:  /* error */
 
192
        return (-1);
 
193
        
 
194
      case 1:           /* retry */
 
195
        return (0);
 
196
      }
 
197
    }
 
198
  
 
199
  if (ioctl(d->fd, CDIOCREADSUBCHANNEL, &sc)) 
 
200
    {
 
201
      /* we need to release the device so the kernel will notice
 
202
         reloaded media */
 
203
      (void) close(d->fd);
 
204
      d->fd = -1;
 
205
      return (0);       /* ejected */
 
206
    }
 
207
  
 
208
  switch (scd.header.audio_status) 
 
209
    {
 
210
    case CD_AS_PLAY_IN_PROGRESS:
 
211
      *mode = WM_CDM_PLAYING;
 
212
    dopos:
 
213
      *pos = scd.what.position.absaddr.msf.minute * 60 * 75 +
 
214
        scd.what.position.absaddr.msf.second * 75 +
 
215
        scd.what.position.absaddr.msf.frame;
 
216
      *track = scd.what.position.track_number;
 
217
      *index = scd.what.position.index_number;
 
218
      break;
 
219
      
 
220
    case CD_AS_PLAY_PAUSED:
 
221
      if (oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_PAUSED)
 
222
        {
 
223
          *mode = WM_CDM_PAUSED;
 
224
          goto dopos;
 
225
        }
 
226
      else
 
227
        *mode = WM_CDM_STOPPED;
 
228
      break;
 
229
      
 
230
    case CD_AS_PLAY_COMPLETED:
 
231
      *mode = WM_CDM_TRACK_DONE; /* waiting for next track. */
 
232
      break;
 
233
      
 
234
    case CD_AS_NO_STATUS:
 
235
    case 0:
 
236
      *mode = WM_CDM_STOPPED;
 
237
      break;
 
238
    }
 
239
  
 
240
  return (0);
 
241
} /* gen_get_drive_status() */
 
242
 
 
243
/*
 
244
 * Get the number of tracks on the CD.
 
245
 */
 
246
int
 
247
gen_get_trackcount(struct wm_drive *d, int tracks)
 
248
{
 
249
  struct ioc_toc_header hdr;
 
250
  
 
251
  if (ioctl(d->fd, CDIOREADTOCHEADER, &hdr) == -1)
 
252
    return (-1);
 
253
  
 
254
  *tracks = hdr.ending_track - hdr.starting_track + 1; 
 
255
  return (0);
 
256
} /* gen_get_trackcount() */
 
257
 
 
258
/*
 
259
 * Get the start time and mode (data or audio) of a track.
 
260
 *
 
261
 * XXX - this should get cached, but that means keeping track of ejects.
 
262
 */
 
263
int
 
264
gen_get_trackinfo(struct wm_drive *d, int track, int *data, int *startframe)
 
265
{
 
266
  struct ioc_read_toc_entry     toc;
 
267
  struct cd_toc_entry           toc_buffer;
 
268
  
 
269
  bzero((char *)&toc_buffer, sizeof(toc_buffer));
 
270
  toc.address_format = CD_MSF_FORMAT;
 
271
  toc.starting_track = track;
 
272
  toc.data_len = sizeof(toc_buffer);
 
273
  toc.data = &toc_buffer;
 
274
  
 
275
  if (ioctl(d->fd, CDIOREADTOCENTRYS, &toc))
 
276
    return (-1);
 
277
  
 
278
  *data = ((toc_buffer.control & 0x4) != 0);
 
279
  
 
280
  *startframe = toc_buffer.addr.msf.minute*60*75 +
 
281
    toc_buffer.addr.msf.second * 75 +
 
282
    toc_buffer.addr.msf.frame;
 
283
  
 
284
  return (0);
 
285
} /* gen_get_trackinfo() */
 
286
 
 
287
/*
 
288
 * Get the number of frames on the CD.
 
289
 */
 
290
int
 
291
gen_get_cdlen(struct wm_drive *d, int *frames)
 
292
{
 
293
  int           tmp;
 
294
  struct ioc_toc_header         hdr;
 
295
  int status;
 
296
  
 
297
#define LEADOUT 0xaa                    /* see scsi.c.  what a hack! */
 
298
  return gen_get_trackinfo(d, LEADOUT, &tmp, frames);
 
299
} /* gen_get_cdlen() */
 
300
 
 
301
/*
 
302
 * Play the CD from one position to another (both in frames.)
 
303
 */
 
304
int
 
305
gen_play(struct wm_drive *d, int start, int end)
 
306
{
 
307
  struct ioc_play_msf   msf;
 
308
  
 
309
  msf.start_m   = start / (60*75);
 
310
  msf.start_s   = (start % (60*75)) / 75;
 
311
  msf.start_f   = start % 75;
 
312
  msf.end_m     = end / (60*75);
 
313
  msf.end_s     = (end % (60*75)) / 75;
 
314
  msf.end_f     = end % 75;
 
315
  
 
316
  if (ioctl(d->fd, CDIOCSTART))
 
317
    return (-1);
 
318
  
 
319
  if (ioctl(d->fd, CDIOCPLAYMSF, &msf))
 
320
    return (-2);
 
321
  
 
322
  return (0);
 
323
} /* gen_play() */
 
324
 
 
325
/*
 
326
 * Pause the CD.
 
327
 */
 
328
int
 
329
gen_pause(struct wm_drive *d)
 
330
{
 
331
  return (ioctl(d->fd, CDIOCPAUSE));
 
332
} /* gen_pause() */
 
333
 
 
334
/*
 
335
 * Resume playing the CD (assuming it was paused.)
 
336
 */
 
337
int
 
338
gen_resume(struct wm_drive *d)
 
339
{
 
340
  return (ioctl(d->fd, CDIOCRESUME));
 
341
} /* gen_resume() */
 
342
 
 
343
/*
 
344
 * Stop the CD.
 
345
 */
 
346
int
 
347
gen_stop(struct wm_drive *d)
 
348
{
 
349
  return (ioctl(d->fd, CDIOCSTOP));
 
350
} /* gen_stop() */
 
351
 
 
352
/*
 
353
 * Eject the current CD, if there is one.
 
354
 */
 
355
int
 
356
gen_eject(struct wm_drive *d)
 
357
{
 
358
  /* On some systems, we can check to see if the CD is mounted. */
 
359
  struct stat   stbuf;
 
360
  struct statfs buf;
 
361
  int rval;
 
362
  
 
363
  if (fstat(d->fd, &stbuf) != 0)
 
364
    return (-2);
 
365
  
 
366
  /* Is this a mounted filesystem? */
 
367
  if (fstatfs(stbuf.st_rdev, &buf) == 0)
 
368
    return (-3);
 
369
  
 
370
  rval = ioctl(d->fd, CDIOCALLOW);
 
371
  if (rval == 0)
 
372
    rval = ioctl(d->fd, CDIOCEJECT);
 
373
  if (rval == 0)
 
374
    rval = ioctl(d->fd, CDIOCPREVENT);
 
375
  if (rval == 0)
 
376
    rval = close(d->fd);
 
377
  if (rval == 0)
 
378
    d->fd = -1;
 
379
  return rval;
 
380
} /* gen_eject() */
 
381
 
 
382
/*----------------------------------------*
 
383
 * Close the CD tray
 
384
 *
 
385
 * Please edit and send changes to
 
386
 * milliByte@DeathsDoor.com
 
387
 *----------------------------------------*/
 
388
 
 
389
int 
 
390
gen_closetray(struct wm_drive *d)
 
391
{
 
392
#ifdef CAN_CLOSE
 
393
  if(!close(d->fd))
 
394
    {
 
395
      d->fd=-1;
 
396
      return(wmcd_reopen(d));
 
397
    } else {
 
398
      return(-1);
 
399
    }
 
400
#else
 
401
  /* Always succeed if the drive can't close */
 
402
  return(0);
 
403
#endif /* CAN_CLOSE */
 
404
} /* gen_closetray() */
 
405
 
 
406
/*
 
407
 * scale_volume(vol, max)
 
408
 *
 
409
 * Return a volume value suitable for passing to the CD-ROM drive.  "vol"
 
410
 * is a volume slider setting; "max" is the slider's maximum value.
 
411
 *
 
412
 * On Sun and DEC CD-ROM drives, the amount of sound coming out the jack
 
413
 * increases much faster toward the top end of the volume scale than it
 
414
 * does at the bottom.  To make up for this, we make the volume scale look
 
415
 * sort of logarithmic (actually an upside-down inverse square curve) so
 
416
 * that the volume value passed to the drive changes less and less as you
 
417
 * approach the maximum slider setting.  The actual formula looks like
 
418
 *
 
419
 *     (max^2 - (max - vol)^2) * (max_volume - min_volume)
 
420
 * v = --------------------------------------------------- + min_volume
 
421
 *                           max^2
 
422
 *
 
423
 * If your system's volume settings aren't broken in this way, something
 
424
 * like the following should work:
 
425
 *
 
426
 *      return ((vol * (max_volume - min_volume)) / max + min_volume);
 
427
 */
 
428
static int
 
429
scale_volume(int vol, int max)
 
430
{
 
431
  return ((vol * (max_volume - min_volume)) / max + min_volume);
 
432
} /* scale_volume() */
 
433
 
 
434
/*
 
435
 * unscale_volume(cd_vol, max)
 
436
 *
 
437
 * Given a value between min_volume and max_volume, return the volume slider
 
438
 * value needed to achieve that value.
 
439
 *
 
440
 * Rather than perform floating-point calculations to reverse the above
 
441
 * formula, we simply do a binary search of scale_volume()'s return values.
 
442
 */
 
443
static int
 
444
unscale_volume(int cd_vol, int max)
 
445
{
 
446
        int     vol = 0, top = max, bot = 0, scaled;
 
447
 
 
448
        while (bot <= top)
 
449
        {
 
450
                vol = (top + bot) / 2;
 
451
                scaled = scale_volume(vol, max);
 
452
                if (cd_vol == scaled)
 
453
                        break;
 
454
                if (cd_vol < scaled)
 
455
                        top = vol - 1;
 
456
                else
 
457
                        bot = vol + 1;
 
458
        }
 
459
        
 
460
        if (vol < 0)
 
461
                vol = 0;
 
462
        else if (vol > max)
 
463
                vol = max;
 
464
 
 
465
        return (vol);
 
466
} /* unscale_volume() */
 
467
 
 
468
/*
 
469
 * Set the volume level for the left and right channels.  Their values
 
470
 * range from 0 to 100.
 
471
 */
 
472
int
 
473
gen_set_volume(struct wm_drive *d, int left, int right)
 
474
{
 
475
  struct ioc_vol vol;
 
476
  
 
477
  if (left < 0) /* don't laugh, I saw this happen once! */
 
478
    left = 0;
 
479
  if (right < 0)
 
480
    right = 0;
 
481
  left = scale_volume(left, 100);
 
482
  right = scale_volume(right, 100);
 
483
  
 
484
  bzero((char *)&vol, sizeof(vol));
 
485
  
 
486
  vol.vol[LEFT_PORT] = left;
 
487
  vol.vol[RIGHT_PORT] = right;
 
488
  
 
489
  if (ioctl(d->fd, CDIOCSETVOL, &vol))
 
490
    return (-1);
 
491
  
 
492
  return (0);
 
493
} /* gen_set_volume() */
 
494
 
 
495
 
 
496
/*
 
497
 * Read the initial volume from the drive, if available.  Each channel
 
498
 * ranges from 0 to 100, with -1 indicating data not available.
 
499
 */
 
500
int
 
501
gen_get_volume(struct wm_drive *d, int *left, int *right)
 
502
{
 
503
  struct ioc_vol vol;
 
504
  
 
505
  if (d->fd >= 0)
 
506
    {
 
507
      bzero((char *)&vol, sizeof(vol));
 
508
      
 
509
      if (ioctl(d->fd, CDIOCGETVOL, &vol))
 
510
        *left = *right = -1;
 
511
      else
 
512
        {
 
513
          *left = unscale_volume(vol.vol[LEFT_PORT], 100);
 
514
          *right = unscale_volume(vol.vol[RIGHT_PORT], 100);
 
515
        }
 
516
    }
 
517
  else
 
518
    *left = *right = -1;
 
519
  
 
520
  return (0);
 
521
} /* gen_get_volume() */
 
522
 
 
523
/*------------------------------------------------------------------------*
 
524
 * gen_get_cdtext(drive, buffer, lenght)
 
525
 *------------------------------------------------------------------------*/
 
526
 
 
527
int
 
528
gen_get_cdtext(struct wm_drive *d, unsigned char **pp_buffer, int *p_buffer_lenght)
 
529
{
 
530
  return -1; /* no SCSI, no CDTEXT */
 
531
} /* gen_get_cdtext() */
 
532
 
 
533
#endif