Exemplo n.º 1
0
Arquivo: siofile.c Projeto: t6/sndio
void
dev_sio_stop(struct dev *d)
{
	if (!sio_eof(d->sio.hdl) && !sio_stop(d->sio.hdl)) {
		if (log_level >= 1) {
			dev_log(d);
			log_puts(": failed to stop device\n");
		}
		return;
	}
#ifdef DEBUG
	if (log_level >= 3) {
		dev_log(d);
		log_puts(": stopped, load avg = ");
		log_puti(d->sio.sum_utime / 1000);
		log_puts(" / ");
		log_puti(d->sio.sum_wtime / 1000);
		log_puts("\n");
	}
#endif
	timo_del(&d->sio.watchdog);
}
Exemplo n.º 2
0
Arquivo: siofile.c Projeto: t6/sndio
void
dev_sio_onmove(void *arg, int delta)
{
	struct dev *d = arg;

#ifdef DEBUG
	if (log_level >= 4) {
		dev_log(d);
		log_puts(": tick, delta = ");
		log_puti(delta);
		log_puts("\n");
	}
	d->sio.sum_utime += file_utime - d->sio.utime;
	d->sio.sum_wtime += file_wtime - d->sio.wtime;
	d->sio.wtime = file_wtime;
	d->sio.utime = file_utime;
	if (d->mode & MODE_PLAY)
		d->sio.pused -= delta;
	if (d->mode & MODE_REC)
		d->sio.rused += delta;
#endif
	dev_onmove(d, delta);
}
Exemplo n.º 3
0
static int
fdpass_send(struct fdpass *f, int cmd, int num, int mode, int fd)
{
	struct fdpass_msg data;
	struct msghdr msg;
	struct cmsghdr *cmsg;
	union {
		struct cmsghdr hdr;
		unsigned char buf[CMSG_SPACE(sizeof(int))];
	} cmsgbuf;
	struct iovec iov;
	ssize_t n;

	data.cmd = cmd;
	data.num = num;
	data.mode = mode;
	iov.iov_base = &data;
	iov.iov_len = sizeof(struct fdpass_msg);
	memset(&msg, 0, sizeof(msg));
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	if (fd >= 0) {
		msg.msg_control = &cmsgbuf.buf;
		msg.msg_controllen = sizeof(cmsgbuf.buf);
		cmsg = CMSG_FIRSTHDR(&msg);
		cmsg->cmsg_len = CMSG_LEN(sizeof(int));
		cmsg->cmsg_level = SOL_SOCKET;
		cmsg->cmsg_type = SCM_RIGHTS;
		*(int *)CMSG_DATA(cmsg) = fd;
	}
	n = sendmsg(f->fd, &msg, 0);
	if (n < 0) {
		if (log_level >= 1) {
			fdpass_log(f);
			log_puts(": sendmsg failed\n");
		}
		fdpass_close(f);
		return 0;
	}
	if (n != sizeof(struct fdpass_msg)) {
		if (log_level >= 1) {
			fdpass_log(f);
			log_puts(": short write\n");
		}
		fdpass_close(f);
		return 0;
	}
#ifdef DEBUG
	if (log_level >= 3) {
		fdpass_log(f);
		log_puts(": send: cmd = ");
		log_puti(cmd);
		log_puts(", num = ");
		log_puti(num);
		log_puts(", mode = ");
		log_puti(mode);
		log_puts(", fd = ");
		log_puti(fd);
		log_puts("\n");
	}
#endif
	if (fd >= 0)
		close(fd);
	return 1;
}
Exemplo n.º 4
0
static int
fdpass_recv(struct fdpass *f, int *cmd, int *num, int *mode, int *fd)
{
	struct fdpass_msg data;
	struct msghdr msg;
	struct cmsghdr *cmsg;
	union {
		struct cmsghdr hdr;
		unsigned char buf[CMSG_SPACE(sizeof(int))];
	} cmsgbuf;
	struct iovec iov;
	ssize_t n;

	iov.iov_base = &data;
	iov.iov_len = sizeof(struct fdpass_msg);
	memset(&msg, 0, sizeof(msg));
	msg.msg_control = &cmsgbuf.buf;
	msg.msg_controllen = sizeof(cmsgbuf.buf);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	n = recvmsg(f->fd, &msg, MSG_WAITALL);
	if (n < 0 && errno == EMSGSIZE) {
		if (log_level >= 1) {
			fdpass_log(f);
			log_puts(": out of fds\n");
		}
		/*
		 * ancillary data (ie the fd) is discarded,
		 * retrieve the message
		 */
		n = recvmsg(f->fd, &msg, MSG_WAITALL);
	}
	if (n < 0) {
		if (log_level >= 1) {
			fdpass_log(f);
			log_puts(": recvmsg failed\n");
		}
		fdpass_close(f);
		return 0;
	}
	if (n == 0) {
		if (log_level >= 3) {
			fdpass_log(f);
			log_puts(": recvmsg eof\n");
		}
		fdpass_close(f);
		return 0;
	}
	if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) {
		if (log_level >= 1) {
			fdpass_log(f);
			log_puts(": truncated\n");
		}
		fdpass_close(f);
		return 0;
	}
	cmsg = CMSG_FIRSTHDR(&msg);
	for (;;) {
		if (cmsg == NULL) {
			*fd = -1;
			break;
		}
		if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) &&
		    cmsg->cmsg_level == SOL_SOCKET &&
		    cmsg->cmsg_type == SCM_RIGHTS) {
			*fd = *(int *)CMSG_DATA(cmsg);
			break;
		}
		cmsg = CMSG_NXTHDR(&msg, cmsg);
	}
	*cmd = data.cmd;
	*num = data.num;
	*mode = data.mode;
#ifdef DEBUG
	if (log_level >= 3) {
		fdpass_log(f);
		log_puts(": recv: cmd = ");
		log_puti(*cmd);
		log_puts(", num = ");
		log_puti(*num);
		log_puts(", mode = ");
		log_puti(*mode);
		log_puts(", fd = ");
		log_puti(*fd);
		log_puts("\n");
	}
#endif
	return 1;
}
Exemplo n.º 5
0
Arquivo: siofile.c Projeto: t6/sndio
void
dev_sio_run(void *arg)
{
	struct dev *d = arg;
	unsigned char *data, *base;
	unsigned int n;

	/*
	 * sio_read() and sio_write() would block at the end of the
	 * cycle so we *must* return and restart poll()'ing. Otherwise
	 * we may trigger dev_cycle() which would make all clients
	 * underrun (ex, on a play-only device)
	 */
	for (;;) {
		if (d->pstate != DEV_RUN)
			return;
		switch (d->sio.cstate) {
		case DEV_SIO_READ:
#ifdef DEBUG
			if (!(d->sio.events & POLLIN)) {
				dev_log(d);
				log_puts(": recording, but POLLIN not set\n");
				panic();
			}
			if (d->sio.todo == 0) {
				dev_log(d);
				log_puts(": can't read data\n");
				panic();
			}
			if (d->prime > 0) {
				dev_log(d);
				log_puts(": unexpected data\n");
				panic();
			}
#endif
			base = d->decbuf ? d->decbuf : (unsigned char *)d->rbuf;
			data = base +
			    d->rchan * d->round * d->par.bps -
			    d->sio.todo;
			n = sio_read(d->sio.hdl, data, d->sio.todo);
			d->sio.todo -= n;
#ifdef DEBUG
			if (log_level >= 4) {
				dev_log(d);
				log_puts(": read ");
				log_putu(n);
				log_puts(": bytes, todo ");
				log_putu(d->sio.todo);
				log_puts("/");
				log_putu(d->round * d->rchan * d->par.bps);
				log_puts("\n");
			}
#endif
			if (d->sio.todo > 0)
				return;
#ifdef DEBUG
			d->sio.rused -= d->round;
			if (log_level >= 2) {
				if (d->sio.rused >= d->round) {
					dev_log(d);
					log_puts(": rec hw xrun, rused = ");
					log_puti(d->sio.rused);
					log_puts("/");
					log_puti(d->bufsz);
					log_puts("\n");
				}
				if (d->sio.rused < 0 ||
				    d->sio.rused >= d->bufsz) {
					dev_log(d);
					log_puts(": out of bounds rused = ");
					log_puti(d->sio.rused);
					log_puts("/");
					log_puti(d->bufsz);
					log_puts("\n");
				}
			}
#endif
			d->sio.cstate = DEV_SIO_CYCLE;
			break;
		case DEV_SIO_CYCLE:
			timo_del(&d->sio.watchdog);
			timo_add(&d->sio.watchdog, WATCHDOG_USEC);

#ifdef DEBUG
			/*
			 * check that we're called at cycle boundary:
			 * either after a recorded block, or when POLLOUT is
			 * raised
			 */
			if (!((d->mode & MODE_REC) && d->prime == 0) &&
			    !(d->sio.events & POLLOUT)) {
				dev_log(d);
				log_puts(": cycle not at block boundary\n");
				panic();
			}
#endif
			dev_cycle(d);
			if (d->mode & MODE_PLAY) {
				d->sio.cstate = DEV_SIO_WRITE;
				d->sio.todo = d->round * d->pchan * d->par.bps;
				break;
			} else {
				d->sio.cstate = DEV_SIO_READ;
				d->sio.todo = d->round * d->rchan * d->par.bps;
				return;
			}
		case DEV_SIO_WRITE:
#ifdef DEBUG
			if (d->sio.todo == 0) {
				dev_log(d);
				log_puts(": can't write data\n");
				panic();
			}
#endif
			base = d->encbuf ? d->encbuf : (unsigned char *)DEV_PBUF(d);
			data = base +
			    d->pchan * d->round * d->par.bps -
			    d->sio.todo;
			n = sio_write(d->sio.hdl, data, d->sio.todo);
			d->sio.todo -= n;
#ifdef DEBUG
			if (log_level >= 4) {
				dev_log(d);
				log_puts(": wrote ");
				log_putu(n);
				log_puts(" bytes, todo ");
				log_putu(d->sio.todo);
				log_puts("/");
				log_putu(d->round * d->pchan * d->par.bps);
				log_puts("\n");
			}
#endif
			if (d->sio.todo > 0)
				return;
#ifdef DEBUG
			d->sio.pused += d->round;
			if (log_level >= 2) {
				if (d->prime == 0 &&
				    d->sio.pused <= d->bufsz - d->round) {
					dev_log(d);
					log_puts(": play hw xrun, pused = ");
					log_puti(d->sio.pused);
					log_puts("/");
					log_puti(d->bufsz);
					log_puts("\n");
				}
				if (d->sio.pused < 0 ||
				    d->sio.pused > d->bufsz) {
					/* device driver or libsndio bug */
					dev_log(d);
					log_puts(": out of bounds pused = ");
					log_puti(d->sio.pused);
					log_puts("/");
					log_puti(d->bufsz);
					log_puts("\n");
				}
			}
#endif
			d->poffs += d->round;
			if (d->poffs == d->psize)
				d->poffs = 0;
			if ((d->mode & MODE_REC) && d->prime == 0) {
				d->sio.cstate = DEV_SIO_READ;
				d->sio.todo = d->round * d->rchan * d->par.bps;
			} else
				d->sio.cstate = DEV_SIO_CYCLE;
			return;
		}
	}
}