"Fossies" - the Fresh Open Source Software Archive

Member "alsa-oss-1.1.8/alsa/alsa-oss.c" (7 Jan 2019, 18801 Bytes) of package /linux/misc/alsa-oss-1.1.8.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "alsa-oss.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.0.28_vs_1.1.6.

    1 /*
    2  *  OSS -> ALSA compatibility layer
    3  *  Copyright (c) by Abramo Bagnara <abramo@alsa-project.org>,
    4  *           Jaroslav Kysela <perex@perex.cz>
    5  *
    6  *
    7  *   This program is free software; you can redistribute it and/or modify
    8  *   it under the terms of the GNU General Public License as published by
    9  *   the Free Software Foundation; either version 2 of the License, or
   10  *   (at your option) any later version.
   11  *
   12  *   This program is distributed in the hope that it will be useful,
   13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15  *   GNU General Public License for more details.
   16  *
   17  *   You should have received a copy of the GNU General Public License
   18  *   along with this program; if not, write to the Free Software
   19  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
   20  *
   21  */
   22 
   23 #define _GNU_SOURCE
   24 
   25 #include <sys/types.h>
   26 #include <sys/time.h>
   27 #include <sys/stat.h>
   28 #include <sys/poll.h>
   29 #include <sys/select.h>
   30 #include <sys/mman.h>
   31 #include <stdarg.h>
   32 #include <unistd.h>
   33 #include <fcntl.h>
   34 #include <dlfcn.h>
   35 #include <stdio.h>
   36 #include <stdlib.h>
   37 #include <string.h>
   38 #include <limits.h>
   39 #include <errno.h>
   40 #include <assert.h>
   41 
   42 #include "alsa-oss-emul.h"
   43 
   44 #ifndef ATTRIBUTE_UNUSED
   45 /** do not print warning (gcc) when function parameter is not used */
   46 #define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
   47 #endif
   48 
   49 #if 1
   50 #define DEBUG_POLL
   51 #define DEBUG_SELECT
   52 #ifdef NEW_MACRO_VARARGS
   53 #define DEBUG(...) do { if (oss_wrapper_debug) fprintf(stderr, __VA_ARGS__); } while (0)
   54 #else /* !NEW_MACRO_VARARGS */
   55 #define DEBUG(args...) do { if (oss_wrapper_debug) fprintf(stderr, ##args); } while (0)
   56 #endif
   57 #else
   58 #ifdef NEW_MACRO_VARARGS
   59 #define DEBUG(...)
   60 #else /* !NEW_MACRO_VARARGS */
   61 #define DEBUG(args...)
   62 #endif
   63 #endif
   64 
   65 #ifndef O_LARGEFILE
   66 #define O_LARGEFILE 0100000
   67 #endif
   68 
   69 static int (*_select)(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
   70 static int (*_poll)(struct pollfd *ufds, unsigned int nfds, int timeout);
   71 static int (*_open)(const char *file, int oflag, ...);
   72 static int (*_open64)(const char *file, int oflag, ...);
   73 static int (*_close)(int fd);
   74 static ssize_t (*_write)(int fd, const void *buf, size_t n);
   75 static ssize_t (*_read)(int fd, void *buf, size_t n);
   76 static int (*_ioctl)(int fd, unsigned long request, ...);
   77 static int (*_fcntl)(int fd, int cmd, ...);
   78 static void *(*_mmap)(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
   79 static int (*_munmap)(void* addr, size_t len);
   80 
   81 static FILE *(*_fopen)(const char *path, const char *mode);
   82 static FILE *(*_fopen64)(const char *path, const char *mode);
   83 
   84 typedef struct ops {
   85     int (*close)(int fd);
   86     ssize_t (*write)(int fd, const void *buf, size_t n);
   87     ssize_t (*read)(int fd, void *buf, size_t n);
   88     int (*ioctl)(int fd, unsigned long request, ...);
   89     int (*fcntl)(int fd, int cmd, ...);
   90     void *(*mmap)(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
   91     int (*munmap)(void* addr, size_t len);
   92 } ops_t;
   93 
   94 typedef enum {
   95     FD_OSS_DSP,
   96     FD_OSS_MIXER,
   97     FD_CLASSES,
   98 } fd_class_t;                                                            
   99 
  100 static ops_t ops[FD_CLASSES];
  101 
  102 typedef struct {
  103     fd_class_t class;
  104     int oflags;
  105     void *mmap_area;
  106     int poll_fds;
  107 } fd_t;
  108 
  109 static void initialize(void);
  110 static int initialized = 0;
  111 
  112 static int oss_wrapper_debug = 0;
  113 static int open_max;
  114 static int poll_fds_add = 0;
  115 static fd_t **fds;
  116 
  117 static inline int is_oss_device(int fd)
  118 {
  119     return fd >= 0 && fd < open_max && fds[fd];
  120 }
  121 
  122 static int is_dsp_device(const char *pathname)
  123 {
  124     if(!pathname) return 0;
  125     if(strncmp(pathname,"/dev/dsp",8) == 0) return 1;
  126     if(strncmp(pathname,"/dev/adsp",9) == 0) return 1;
  127     if(strncmp(pathname,"/dev/audio",10) == 0) return 1;
  128     if(strncmp(pathname,"/dev/sound/dsp",14) == 0) return 1;
  129     if(strncmp(pathname,"/dev/sound/adsp",15) == 0) return 1;
  130     if(strncmp(pathname,"/dev/sound/audio",16) == 0) return 1;
  131     return 0;
  132 }
  133 
  134 static int is_mixer_device(const char *pathname)
  135 {
  136     if(!pathname) return 0;
  137     if(strncmp(pathname,"/dev/mixer",10) == 0) return 1;
  138     if(strncmp(pathname,"/dev/sound/mixer",16) == 0) return 1;
  139     return 0;
  140 }
  141 
  142 static int oss_pcm_fcntl(int fd, int cmd, ...)
  143 {
  144     int result;
  145     va_list args;
  146     long arg;
  147 
  148     if (!initialized)
  149         initialize();
  150 
  151     va_start(args, cmd);
  152     arg = va_arg(args, long);
  153     va_end(args);
  154 
  155     switch (cmd) {
  156     case F_GETFL:
  157         return fds[fd]->oflags;
  158         case F_SETFL:
  159         result = lib_oss_pcm_nonblock(fd, (arg & O_NONBLOCK) ? 1 : 0);
  160                 if (result < 0) {
  161                         errno = -result;
  162                         return -1;
  163                 }
  164                 return 0;
  165     default:
  166         DEBUG("pcm_fcntl(%d, ", fd);
  167         result = _fcntl(fd, cmd, arg);
  168         if (result < 0)
  169             return result;
  170         DEBUG("%x, %ld)\n", cmd, arg);
  171         return result;
  172     }
  173     return -1;
  174 }
  175 
  176 static int oss_mixer_fcntl(int fd, int cmd, ...)
  177 {
  178     int result;
  179     va_list args;
  180     long arg;
  181 
  182     va_start(args, cmd);
  183     arg = va_arg(args, long);
  184     va_end(args);
  185 
  186     switch (cmd) {
  187     case F_GETFL:
  188         return fds[fd]->oflags;
  189     default:
  190         DEBUG("mixer_fcntl(%d, ", fd);
  191         result = _fcntl(fd, cmd, arg);
  192         if (result < 0)
  193             return result;
  194         DEBUG("%x, %ld)\n", cmd, arg);
  195         return result;
  196     }
  197     return -1;
  198 }
  199 
  200 static ssize_t bad_write(int fd ATTRIBUTE_UNUSED, const void *buf ATTRIBUTE_UNUSED, size_t n ATTRIBUTE_UNUSED)
  201 {
  202     errno = EBADFD;
  203     return -1;
  204 }
  205 
  206 static ssize_t bad_read(int fd ATTRIBUTE_UNUSED, void *buf ATTRIBUTE_UNUSED, size_t n ATTRIBUTE_UNUSED)
  207 {
  208     errno = EBADFD;
  209     return -1;
  210 }
  211 
  212 static void *bad_mmap(void *addr ATTRIBUTE_UNUSED, size_t len ATTRIBUTE_UNUSED,
  213               int prot ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED,
  214               int fd ATTRIBUTE_UNUSED, off_t offset ATTRIBUTE_UNUSED)
  215 {
  216     errno = EBADFD;
  217     return MAP_FAILED;
  218 }
  219 
  220 static int bad_munmap(void* addr ATTRIBUTE_UNUSED, size_t len ATTRIBUTE_UNUSED)
  221 {
  222     errno = EBADFD;
  223     return -1;
  224 }
  225 
  226 static ops_t ops[FD_CLASSES] = {
  227         [FD_OSS_DSP] = {
  228         .close = lib_oss_pcm_close,
  229         .write = lib_oss_pcm_write,
  230         .read = lib_oss_pcm_read,
  231         .ioctl = lib_oss_pcm_ioctl,
  232         .fcntl = oss_pcm_fcntl,
  233         .mmap = lib_oss_pcm_mmap,
  234         .munmap = lib_oss_pcm_munmap,
  235         },
  236         [FD_OSS_MIXER] = {
  237         .close = lib_oss_mixer_close,
  238         .write = bad_write,
  239         .read = bad_read,
  240         .ioctl = lib_oss_mixer_ioctl,
  241         .fcntl = oss_mixer_fcntl,
  242         .mmap = bad_mmap,
  243         .munmap = bad_munmap,
  244     },
  245 };
  246 
  247 static int dsp_open_helper(const char *file, int oflag)
  248 {
  249     int fd;
  250     fd = lib_oss_pcm_open(file, oflag);
  251     if (fd >= 0) {
  252         int nfds;
  253         fds[fd] = calloc(sizeof(fd_t), 1);
  254         if (fds[fd] == NULL) {
  255             ops[FD_OSS_DSP].close(fd);
  256             errno = ENOMEM;
  257             return -1;
  258         }
  259         fds[fd]->class = FD_OSS_DSP;
  260         fds[fd]->oflags = oflag;
  261         nfds = lib_oss_pcm_poll_fds(fd);
  262         if (nfds > 0) {
  263             fds[fd]->poll_fds = nfds;
  264             poll_fds_add += nfds;
  265         }
  266     }
  267     return fd;
  268 }
  269 
  270 static int mixer_open_helper(const char *file, int oflag)
  271 {
  272     int fd;
  273     fd = lib_oss_mixer_open(file, oflag);
  274     if (fd >= 0) {
  275         fds[fd] = calloc(sizeof(fd_t), 1);
  276         if (fds[fd] == NULL) {
  277             ops[FD_OSS_MIXER].close(fd);
  278             errno = ENOMEM;
  279             return -1;
  280         }
  281         fds[fd]->class = FD_OSS_MIXER;
  282         fds[fd]->oflags = oflag;
  283     }
  284     return fd;
  285 } 
  286 
  287 #define DECL_OPEN(name, callback) \
  288 int name(const char *file, int oflag, ...) \
  289 { \
  290     va_list args; \
  291     mode_t mode = 0; \
  292     int fd; \
  293     if (!initialized) \
  294         initialize(); \
  295     if (oflag & O_CREAT) { \
  296         va_start(args, oflag); \
  297         mode = va_arg(args, mode_t); \
  298         va_end(args); \
  299     } \
  300     if (is_dsp_device(file)) \
  301         fd = dsp_open_helper(file, oflag); \
  302     else if (is_mixer_device(file)) \
  303         fd = mixer_open_helper(file, oflag); \
  304     else { \
  305         fd = callback(file, oflag, mode); \
  306         if (fd >= 0) \
  307             assert(fds[fd] == NULL); \
  308     } \
  309     return fd; \
  310 }
  311 
  312 DECL_OPEN(open, _open)
  313 DECL_OPEN(open64, _open64)
  314 
  315 int close(int fd)
  316 {
  317     if (!initialized)
  318         initialize();
  319 
  320     if (! is_oss_device(fd)) {
  321         return _close(fd);
  322     } else {
  323         fd_t *xfd = fds[fd];
  324         int err;
  325 
  326         fds[fd] = NULL;
  327         poll_fds_add -= xfd->poll_fds;
  328         if (poll_fds_add < 0) {
  329             fprintf(stderr, "alsa-oss: poll_fds_add screwed up!\n");
  330             poll_fds_add = 0;
  331         }
  332         err = ops[xfd->class].close(fd);
  333         // assert(err >= 0);
  334         return err;
  335     }
  336 }
  337 
  338 ssize_t write(int fd, const void *buf, size_t n)
  339 {
  340     if (!initialized)
  341         initialize();
  342 
  343     if (! is_oss_device(fd))
  344         return _write(fd, buf, n);
  345     else
  346         return ops[fds[fd]->class].write(fd, buf, n);
  347 }
  348 
  349 ssize_t read(int fd, void *buf, size_t n)
  350 {
  351     if (!initialized)
  352         initialize();
  353 
  354     if (! is_oss_device(fd))
  355         return _read(fd, buf, n);
  356     else
  357         return ops[fds[fd]->class].read(fd, buf, n);
  358 }
  359 
  360 int ioctl(int fd, unsigned long request, ...)
  361 {
  362     va_list args;
  363     void *arg;
  364 
  365     if (!initialized)
  366         initialize();
  367 
  368     va_start(args, request);
  369     arg = va_arg(args, void *);
  370     va_end(args);
  371     if (! is_oss_device(fd))
  372         return _ioctl(fd, request, arg);
  373     else
  374         return ops[fds[fd]->class].ioctl(fd, request, arg);
  375 }
  376 
  377 int fcntl(int fd, int cmd, ...)
  378 {
  379     va_list args;
  380     void *arg;
  381 
  382     if (!initialized)
  383         initialize();
  384 
  385     va_start(args, cmd);
  386     arg = va_arg(args, void *);
  387     va_end(args);
  388     if (! is_oss_device(fd))
  389         return _fcntl(fd, cmd, arg);
  390     else
  391         return ops[fds[fd]->class].fcntl(fd, cmd, arg);
  392 }
  393 
  394 void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
  395 {
  396     void *result;
  397 
  398     if (!initialized)
  399         initialize();
  400 
  401     if (! is_oss_device(fd))
  402         return _mmap(addr, len, prot, flags, fd, offset);
  403     result = ops[fds[fd]->class].mmap(addr, len, prot, flags, fd, offset);
  404     if (result != NULL && result != MAP_FAILED)
  405         fds[fd]->mmap_area = result;
  406     return result;
  407 }
  408 
  409 int munmap(void *addr, size_t len)
  410 {
  411     int fd;
  412 
  413     if (!initialized)
  414         initialize();
  415 
  416     for (fd = 0; fd < open_max; ++fd) {
  417         if (fds[fd] && fds[fd]->mmap_area == addr)
  418             break;
  419     }
  420     if (fd >= open_max)
  421         return _munmap(addr, len);
  422     fds[fd]->mmap_area = 0;
  423     return ops[fds[fd]->class].munmap(addr, len);
  424 }
  425 
  426 #ifdef DEBUG_POLL
  427 void dump_poll(struct pollfd *pfds, unsigned long nfds, int timeout)
  428 {
  429     unsigned int k;
  430     fprintf(stderr, "POLL nfds: %ld, timeout: %d\n", nfds, timeout);
  431     for (k = 0; k < nfds; ++k) {
  432         fprintf(stderr, "fd=%d, events=%x, revents=%x\n", 
  433             pfds[k].fd, pfds[k].events, pfds[k].revents);
  434     }
  435 }
  436 #endif
  437 
  438 #ifdef DEBUG_SELECT
  439 void dump_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds,
  440          struct timeval *timeout)
  441 {
  442     int k;
  443     fprintf(stderr, "SELECT nfds: %d, ", nfds);
  444     if (timeout)
  445         fprintf(stderr, "timeout: %ld.%06ld\n", (long)timeout->tv_sec, (long)timeout->tv_usec);
  446     else
  447         fprintf(stderr, "no timeout\n");
  448     if (rfds) {
  449         fprintf(stderr, "rfds: ");
  450         for (k = 0; k < nfds; ++k) {
  451             if (FD_ISSET(k, rfds))
  452                 putc('1', stderr);
  453             else
  454                 putc('0', stderr);
  455         }
  456         putc('\n', stderr);
  457     }
  458     if (wfds) {
  459         fprintf(stderr, "wfds: ");
  460         for (k = 0; k < nfds; ++k) {
  461             if (FD_ISSET(k, wfds))
  462                 putc('1', stderr);
  463             else
  464                 putc('0', stderr);
  465         }
  466         putc('\n', stderr);
  467     }
  468     if (efds) {
  469         fprintf(stderr, "efds: ");
  470         for (k = 0; k < nfds; ++k) {
  471             if (FD_ISSET(k, efds))
  472                 putc('1', stderr);
  473             else
  474                 putc('0', stderr);
  475         }
  476         putc('\n', stderr);
  477     }
  478 }
  479 #endif
  480 
  481 static int poll_with_pcm(struct pollfd *pfds, unsigned long nfds, int timeout);
  482 
  483 int poll(struct pollfd *pfds, unsigned long nfds, int timeout)
  484 {
  485     unsigned int k;
  486 
  487     if (!initialized)
  488         initialize();
  489 
  490     for (k = 0; k < nfds; ++k) {
  491         int fd = pfds[k].fd;
  492         if (! is_oss_device(fd))
  493             continue;
  494         if (fds[fd]->class == FD_OSS_DSP)
  495             return poll_with_pcm(pfds, nfds, timeout);
  496     }
  497     return _poll(pfds, nfds, timeout);
  498 }
  499 
  500 
  501 static int poll_with_pcm(struct pollfd *pfds, unsigned long nfds, int timeout)
  502 {
  503     unsigned int k;
  504     unsigned int nfds1;
  505     int count;
  506     struct pollfd pfds1[nfds + poll_fds_add + 16];
  507 
  508     nfds1 = 0;
  509     for (k = 0; k < nfds; ++k) {
  510         int fd = pfds[k].fd;
  511         if (is_oss_device(fd) && fds[fd]->class == FD_OSS_DSP) {
  512             unsigned short events = pfds[k].events;
  513             int fmode = 0;
  514             if ((events & (POLLIN|POLLOUT)) == (POLLIN|POLLOUT))
  515                 fmode = O_RDWR;
  516             else if (events & POLLIN)
  517                 fmode = O_RDONLY;
  518             else
  519                 fmode = O_WRONLY;
  520             count = lib_oss_pcm_poll_prepare(fd, fmode, &pfds1[nfds1]);
  521             if (count < 0)
  522                 return -1;
  523             nfds1 += count;
  524         } else {
  525             pfds1[nfds1] = pfds[k];
  526             nfds1++;
  527         }
  528         if (nfds1 > nfds + poll_fds_add) {
  529             fprintf(stderr, "alsa-oss: Pollfd overflow!\n");
  530             errno = EINVAL;
  531             return -1;
  532         }
  533     }
  534 #ifdef DEBUG_POLL
  535     if (oss_wrapper_debug) {
  536         fprintf(stderr, "Orig enter ");
  537         dump_poll(pfds, nfds, timeout);
  538         fprintf(stderr, "Changed enter ");
  539         dump_poll(pfds1, nfds1, timeout);
  540     }
  541 #endif
  542     count = _poll(pfds1, nfds1, timeout);
  543     if (count <= 0)
  544         return count;
  545     nfds1 = 0;
  546     count = 0;
  547     for (k = 0; k < nfds; ++k) {
  548         int fd = pfds[k].fd;
  549         unsigned int revents;
  550         if (is_oss_device(fd) && fds[fd]->class == FD_OSS_DSP) {
  551             int result = lib_oss_pcm_poll_result(fd, &pfds1[nfds1]);
  552             revents = 0;
  553             if (result < 0) {
  554                 revents |= POLLNVAL;
  555             } else {
  556                 revents |= ((result & OSS_WAIT_EVENT_ERROR) ? POLLERR : 0) |
  557                        ((result & OSS_WAIT_EVENT_READ) ? POLLIN : 0) |
  558                        ((result & OSS_WAIT_EVENT_WRITE) ? POLLOUT : 0);
  559             }
  560             nfds1 += lib_oss_pcm_poll_fds(fd);
  561         } else {
  562             revents = pfds1[nfds1].revents;
  563             nfds1++;
  564         }
  565         pfds[k].revents = revents;
  566         if (revents)
  567             count++;
  568     }
  569 #ifdef DEBUG_POLL
  570     if (oss_wrapper_debug) {
  571         fprintf(stderr, "Changed exit ");
  572         dump_poll(pfds1, nfds1, timeout);
  573         fprintf(stderr, "Orig exit ");
  574         dump_poll(pfds, nfds, timeout);
  575     }
  576 #endif
  577     return count;
  578 }
  579 
  580 static int select_with_pcm(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds,
  581                struct timeval *timeout);
  582 
  583 int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds,
  584        struct timeval *timeout)
  585 {
  586     int fd;
  587 
  588     if (!initialized)
  589         initialize();
  590 
  591     for (fd = 0; fd < nfds; ++fd) {
  592         int r = (rfds && FD_ISSET(fd, rfds));
  593         int w = (wfds && FD_ISSET(fd, wfds));
  594         int e = (efds && FD_ISSET(fd, efds));
  595         if (!(r || w || e))
  596             continue;
  597         if (is_oss_device(fd) && fds[fd]->class == FD_OSS_DSP)
  598             return select_with_pcm(nfds, rfds, wfds, efds, timeout);
  599     }
  600     return _select(nfds, rfds, wfds, efds, timeout);
  601 }
  602 
  603 
  604 static int select_with_pcm(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds,
  605                struct timeval *timeout)
  606 {
  607     fd_set _rfds1, _wfds1, _efds1;
  608     fd_set *rfds1, *wfds1, *efds1;
  609     int fd;
  610     int nfds1 = nfds;
  611     int count;
  612 
  613     if (rfds)
  614         _rfds1 = *rfds;
  615     else
  616         FD_ZERO(&_rfds1);
  617     rfds1 = &_rfds1;
  618     if (wfds)
  619         _wfds1 = *wfds;
  620     else
  621         FD_ZERO(&_wfds1);
  622     wfds1 = &_wfds1;
  623     if (efds) {
  624         _efds1 = *efds;
  625         efds1 = &_efds1;
  626     } else {
  627         efds1 = NULL;
  628     }
  629     for (fd = 0; fd < nfds; ++fd) {
  630         int r = (rfds && FD_ISSET(fd, rfds));
  631         int w = (wfds && FD_ISSET(fd, wfds));
  632         int e = (efds && FD_ISSET(fd, efds));
  633         if (!(r || w || e))
  634             continue;
  635         if (is_oss_device(fd) && fds[fd]->class == FD_OSS_DSP) {
  636             int res, fmode = 0;
  637             
  638             if (r & w)
  639                 fmode = O_RDWR;
  640             else if (r)
  641                 fmode = O_RDONLY;
  642             else
  643                 fmode = O_WRONLY;
  644             res = lib_oss_pcm_select_prepare(fd, fmode, rfds1, wfds1,
  645                              e ? efds1 : NULL);
  646             if (res < 0)
  647                 return -1;
  648             if (nfds1 < res + 1)
  649                 nfds1 = res + 1;
  650             if (r)
  651                 FD_CLR(fd, rfds1);
  652             if (w)
  653                 FD_CLR(fd, wfds1);
  654             if (e)
  655                 FD_CLR(fd, efds1);
  656         }
  657     }
  658 #ifdef DEBUG_SELECT
  659     if (oss_wrapper_debug) {
  660         fprintf(stderr, "Orig enter ");
  661         dump_select(nfds, rfds, wfds, efds, timeout);
  662         fprintf(stderr, "Changed enter ");
  663         dump_select(nfds1, rfds1, wfds1, efds1, timeout);
  664     }
  665 #endif
  666     count = _select(nfds1, rfds1, wfds1, efds1, timeout);
  667     if (count < 0)
  668         return count;
  669     if (count == 0) {
  670         if (rfds)
  671             FD_ZERO(rfds);
  672         if (wfds)
  673             FD_ZERO(wfds);
  674         if (efds)
  675             FD_ZERO(efds);
  676         return 0;
  677     }
  678     count = 0;
  679     for (fd = 0; fd < nfds; ++fd) {
  680         int r = (rfds && FD_ISSET(fd, rfds));
  681         int w = (wfds && FD_ISSET(fd, wfds));
  682         int e = (efds && FD_ISSET(fd, efds));
  683         int r1, w1, e1;
  684         if (!(r || w || e))
  685             continue;
  686         if (is_oss_device(fd) && fds[fd]->class == FD_OSS_DSP) {
  687             int result = lib_oss_pcm_select_result(fd, rfds1, wfds1, efds1);
  688             r1 = w1 = e1 = 0;
  689             if (result < 0 && e) {
  690                 if (efds)
  691                     FD_SET(fd, efds);
  692                 e1 = 1;
  693             } else {
  694                 if (result & OSS_WAIT_EVENT_ERROR) {
  695                     if (efds)
  696                         FD_SET(fd, efds);
  697                     e1 = 1;
  698                 }
  699                 if (result & OSS_WAIT_EVENT_READ) {
  700                     if (rfds)
  701                         FD_SET(fd, rfds);
  702                     r1 = 1;
  703                 }
  704                 if (result & OSS_WAIT_EVENT_WRITE) {
  705                     if (wfds)
  706                         FD_SET(fd, wfds);
  707                     w1 = 1;
  708                 }
  709             }
  710         } else {
  711             r1 = (r && FD_ISSET(fd, rfds1));
  712             w1 = (w && FD_ISSET(fd, wfds1));
  713             e1 = (e && FD_ISSET(fd, efds1));
  714         }
  715         if (r && !r1 && rfds)
  716             FD_CLR(fd, rfds);
  717         if (w && !w1 && wfds)
  718             FD_CLR(fd, wfds);
  719         if (e && !e1 && efds)
  720             FD_CLR(fd, efds);
  721         if (r1 || w1 || e1)
  722             count++;
  723     }
  724 #ifdef DEBUG_SELECT
  725     if (oss_wrapper_debug) {
  726         fprintf(stderr, "Changed exit ");
  727         dump_select(nfds1, rfds1, wfds1, efds1, timeout);
  728         fprintf(stderr, "Orig exit ");
  729         dump_select(nfds, rfds, wfds, efds, timeout);
  730     }
  731 #endif
  732     return count;
  733 }
  734 
  735 
  736 #include "stdioemu.c"
  737 
  738 FILE *fopen(const char* path, const char *mode)
  739 {
  740     if (!initialized)
  741         initialize();
  742 
  743     if (!is_dsp_device(path)) 
  744         return _fopen(path, mode);
  745     
  746     return fake_fopen(path, mode, 0);
  747 }
  748 
  749 FILE *fopen64(const char* path, const char *mode)
  750 {
  751     if (!initialized)   
  752         initialize(); 
  753 
  754     if (!is_dsp_device(path))
  755         return _fopen64(path, mode);
  756 
  757     return fake_fopen(path, mode, O_LARGEFILE);
  758 }
  759 
  760 #if 0
  761 int dup(int fd)
  762 {
  763     return fcntl(fd, F_DUPFD, 0);
  764 }
  765 #endif
  766 
  767 #if 0
  768 int dup2(int fd, int fd2)
  769 {
  770     int save;
  771 
  772     if (fd2 < 0 || fd2 >= open_max) {
  773         errno = EBADF;
  774         return -1;
  775     }
  776     
  777     if (fcntl(fd, F_GETFL) < 0)
  778         return -1;
  779     
  780     if (fd == fd2)
  781         return fd2;
  782     
  783     save = errno;
  784     close(fd2);
  785     errno = save;
  786     
  787     return fcntl(fd, F_DUPFD, fd2);
  788 }
  789 #endif
  790 
  791 # define strong_alias(name, aliasname) \
  792   extern __typeof (name) aliasname __attribute__ ((alias (#name)));
  793 
  794 strong_alias(open, __open);
  795 strong_alias(open64, __open64);
  796 strong_alias(close, __close);
  797 strong_alias(write, __write);
  798 strong_alias(read, __read);
  799 strong_alias(ioctl, __ioctl);
  800 strong_alias(fcntl, __fcntl);
  801 strong_alias(mmap, __mmap);
  802 strong_alias(munmap, __munmap);
  803 strong_alias(poll, __poll);
  804 strong_alias(select, __select);
  805 strong_alias(fopen, __fopen);
  806 strong_alias(fopen64, __fopen64);
  807 
  808 /* called by each override if needed */
  809 static void initialize()
  810 {
  811     char *s = getenv("ALSA_OSS_DEBUG");
  812     if (s)
  813         oss_wrapper_debug = 1;
  814     open_max = sysconf(_SC_OPEN_MAX);
  815     if (open_max < 0)
  816         exit(1);
  817     fds = calloc(open_max, sizeof(*fds));
  818     if (!fds)
  819         exit(1);
  820     _open = dlsym(RTLD_NEXT, "open");
  821     _open64 = dlsym(RTLD_NEXT, "open64");
  822     _close = dlsym(RTLD_NEXT, "close");
  823     _write = dlsym(RTLD_NEXT, "write");
  824     _read = dlsym(RTLD_NEXT, "read");
  825     _ioctl = dlsym(RTLD_NEXT, "ioctl");
  826     _fcntl = dlsym(RTLD_NEXT, "fcntl");
  827     _mmap = dlsym(RTLD_NEXT, "mmap");
  828     _munmap = dlsym(RTLD_NEXT, "munmap");
  829     _select = dlsym(RTLD_NEXT, "select");
  830     _poll = dlsym(RTLD_NEXT, "poll");
  831     _fopen = dlsym(RTLD_NEXT, "fopen");
  832     _fopen64 = dlsym(RTLD_NEXT, "fopen64");
  833     initialized = 1;
  834 }