oss_dsp_stream_t streams[2];
} oss_dsp_t;
-typedef enum { FD_OSS_DSP = 0, FD_DEFAULT = -1, FD_CLOSED = -2 } fd_class_t;
+typedef enum { FD_OSS_DSP = 0 } fd_class_t;
typedef struct {
+ int count;
fd_class_t class;
void *private;
void *mmap_area;
} fd_t;
static int open_max;
-static fd_t *fds;
+static fd_t **fds;
#define RETRY open_max
#define OSS_MAJOR 14
{
int result = 0;
int k;
- oss_dsp_t *dsp = fds[fd].private;
+ oss_dsp_t *dsp = fds[fd]->private;
for (k = 0; k < 2; ++k) {
int err;
oss_dsp_stream_t *str = &dsp->streams[k];
}
fd = _open("/dev/null", oflag & O_ACCMODE);
assert(fd >= 0);
- fds[fd].class = FD_OSS_DSP;
+ fds[fd] = malloc(sizeof(fd_t));
+ fds[fd]->class = FD_OSS_DSP;
dsp = calloc(1, sizeof(oss_dsp_t));
if (!dsp) {
errno = -ENOMEM;
return -1;
}
- fds[fd].private = dsp;
+ fds[fd]->private = dsp;
+ fds[fd]->count = 1;
+ fds[fd]->mmap_area = NULL;
dsp->channels = 1;
dsp->rate = 8000;
dsp->format = format;
case OSS_DEVICE_DSPW:
case OSS_DEVICE_AUDIO:
case OSS_DEVICE_ADSP:
- return oss_dsp_open(card, device, oflag, mode);
+ result = oss_dsp_open(card, device, oflag, mode);
+ DEBUG("open(\"%s\", %d, %d) -> %d\n", file, oflag, mode, result);
+ return result;
default:
return RETRY;
}
static ssize_t oss_dsp_write(int fd, const void *buf, size_t n)
{
ssize_t result;
- oss_dsp_t *dsp = fds[fd].private;
+ oss_dsp_t *dsp = fds[fd]->private;
oss_dsp_stream_t *str = &dsp->streams[SND_PCM_STREAM_PLAYBACK];
snd_pcm_t *pcm = str->pcm;
snd_pcm_uframes_t frames;
static ssize_t oss_dsp_read(int fd, void *buf, size_t n)
{
ssize_t result;
- oss_dsp_t *dsp = fds[fd].private;
+ oss_dsp_t *dsp = fds[fd]->private;
oss_dsp_stream_t *str = &dsp->streams[SND_PCM_STREAM_CAPTURE];
snd_pcm_t *pcm = str->pcm;
snd_pcm_uframes_t frames;
int result, err;
va_list args;
void *arg;
- oss_dsp_t *dsp = fds[fd].private;
+ oss_dsp_t *dsp = fds[fd]->private;
oss_dsp_stream_t *str;
snd_pcm_t *pcm;
int k;
int err;
snd_pcm_t *pcm;
- oss_dsp_t *dsp = fds[fd].private;
+ oss_dsp_t *dsp = fds[fd]->private;
DEBUG("F_SETFL, %ld)\n", arg);
for (k = 0; k < 2; ++k) {
pcm = dsp->streams[k].pcm;
{
int err;
void *result;
- oss_dsp_t *dsp = fds[fd].private;
+ oss_dsp_t *dsp = fds[fd]->private;
oss_dsp_stream_t *str;
str = &dsp->streams[SND_PCM_STREAM_PLAYBACK];
if (!str->pcm)
static int oss_dsp_munmap(int fd, void *addr ATTRIBUTE_UNUSED, size_t len ATTRIBUTE_UNUSED)
{
int err;
- oss_dsp_t *dsp = fds[fd].private;
+ oss_dsp_t *dsp = fds[fd]->private;
oss_dsp_stream_t *str;
DEBUG("munmap(%p, %lu)\n", addr, (unsigned long)len);
str = &dsp->streams[SND_PCM_STREAM_PLAYBACK];
if (!ops[k].open)
continue;
fd = ops[k].open(file, oflag, mode);
- if (fd != RETRY)
- goto _end;
- }
- fd = _open(file, oflag, mode);
- if (fd >= 0) {
- if (fds[fd].class != FD_CLOSED) {
- _close(fd);
- errno = EMFILE;
- return -1;
+ if (fd != RETRY) {
+ if (fd >= 0)
+ fds[fd]->count++;
+ return fd;
}
- fds[fd].class = FD_DEFAULT;
}
- _end:
+ fd = _open(file, oflag, mode);
+ if (fd >= 0)
+ assert(!fds[fd]);
return fd;
}
int close(int fd)
{
- int result;
- if (fd < 0 || fd >= open_max || fds[fd].class < 0)
+ int result = 0;
+ if (fd < 0 || fd >= open_max || !fds[fd] || fds[fd]->count > 1) {
result = _close(fd);
- else
- result = ops[fds[fd].class].close(fd);
- if (result >= 0)
- fds[fd].class = FD_CLOSED;
+ } else {
+ fd_t *f = fds[fd];
+ fds[fd] = 0;
+ f->count--;
+ if (f->count == 0) {
+ result = ops[f->class].close(fd);
+ assert(result >= 0);
+ free(f);
+ }
+ }
return result;
}
ssize_t write(int fd, const void *buf, size_t n)
{
- if (fd < 0 || fd >= open_max || fds[fd].class < 0)
+ if (fd < 0 || fd >= open_max || !fds[fd])
return _write(fd, buf, n);
else
- return ops[fds[fd].class].write(fd, buf, n);
+ return ops[fds[fd]->class].write(fd, buf, n);
}
ssize_t read(int fd, void *buf, size_t n)
{
- if (fd < 0 || fd >= open_max || fds[fd].class < 0)
+ if (fd < 0 || fd >= open_max || !fds[fd])
return _read(fd, buf, n);
else
- return ops[fds[fd].class].read(fd, buf, n);
+ return ops[fds[fd]->class].read(fd, buf, n);
}
int ioctl(int fd, unsigned long request, ...)
va_start(args, request);
arg = va_arg(args, void *);
va_end(args);
- if (fd < 0 || fd >= open_max || fds[fd].class < 0)
+ if (fd < 0 || fd >= open_max || !fds[fd])
return _ioctl(fd, request, arg);
else
- return ops[fds[fd].class].ioctl(fd, request, arg);
+ return ops[fds[fd]->class].ioctl(fd, request, arg);
}
int fcntl(int fd, int cmd, ...)
va_start(args, cmd);
arg = va_arg(args, void *);
va_end(args);
- if (fd < 0 || fd >= open_max || fds[fd].class < 0)
+ if (fd < 0 || fd >= open_max || !fds[fd])
return _fcntl(fd, cmd, arg);
else
- return ops[fds[fd].class].fcntl(fd, cmd, arg);
+ return ops[fds[fd]->class].fcntl(fd, cmd, arg);
}
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
{
void *result;
- if (fd < 0 || fd >= open_max || fds[fd].class < 0)
+ if (fd < 0 || fd >= open_max || !fds[fd])
return _mmap(addr, len, prot, flags, fd, offset);
- result = ops[fds[fd].class].mmap(addr, len, prot, flags, fd, offset);
+ result = ops[fds[fd]->class].mmap(addr, len, prot, flags, fd, offset);
if (result != NULL && result != MAP_FAILED)
- fds[fd].mmap_area = result;
+ fds[fd]->mmap_area = result;
return result;
}
return _munmap(addr, len);
#endif
for (fd = 0; fd < open_max; ++fd) {
- if (fds[fd].mmap_area == addr)
+ if (fds[fd]->mmap_area == addr)
break;
}
- if (fd >= open_max || fds[fd].class < 0)
+ if (fd >= open_max || !fds[fd])
return _munmap(addr, len);
else {
- fds[fd].mmap_area = 0;
- return ops[fds[fd].class].munmap(fd, addr, len);
+ fds[fd]->mmap_area = 0;
+ return ops[fds[fd]->class].munmap(fd, addr, len);
}
}
for (k = 0; k < nfds; ++k) {
int fd = pfds[k].fd;
pfds[k].revents = 0;
- if (fd >= open_max)
+ if (fd >= open_max || !fds[fd])
goto _std1;
- switch (fds[fd].class) {
+ switch (fds[fd]->class) {
case FD_OSS_DSP:
{
- oss_dsp_t *dsp = fds[fd].private;
+ oss_dsp_t *dsp = fds[fd]->private;
oss_dsp_stream_t *str;
int j;
for (j = 0; j < 2; ++j) {
for (k = 0; k < nfds; ++k) {
int fd = pfds[k].fd;
unsigned int revents;
- if (fd >= open_max)
+ if (fd >= open_max || !fds[fd])
goto _std2;
- switch (fds[fd].class) {
+ switch (fds[fd]->class) {
case FD_OSS_DSP:
{
- oss_dsp_t *dsp = fds[fd].private;
+ oss_dsp_t *dsp = fds[fd]->private;
oss_dsp_stream_t *str;
int j;
revents = 0;
int e = (efds && FD_ISSET(fd, efds));
if (!(r || w || e))
continue;
- switch (fds[fd].class) {
+ if (!fds[fd])
+ continue;
+ switch (fds[fd]->class) {
case FD_OSS_DSP:
{
- oss_dsp_t *dsp = fds[fd].private;
+ oss_dsp_t *dsp = fds[fd]->private;
oss_dsp_stream_t *str;
int j;
if (r)
int r1, w1, e1;
if (!(r || w || e))
continue;
- switch (fds[fd].class) {
+ if (!fds[fd])
+ continue;
+ switch (fds[fd]->class) {
case FD_OSS_DSP:
{
- oss_dsp_t *dsp = fds[fd].private;
+ oss_dsp_t *dsp = fds[fd]->private;
oss_dsp_stream_t *str;
int j;
r1 = w1 = e1 = 0;
static void initialize()
{
- int k;
char *s = getenv("ALSA_OSS_DEBUG");
if (s)
debug = 1;
_munmap = dlsym(RTLD_NEXT, "munmap");
_select = dlsym(RTLD_NEXT, "select");
_poll = dlsym(RTLD_NEXT, "poll");
- for (k = 0; k < open_max; ++k) {
- fds[k].private = 0;
- if (_fcntl(k, F_GETFL) < 0)
- fds[k].class = FD_CLOSED;
- else
- fds[k].class = FD_DEFAULT;
- }
}