1*dd964a88Sratchov /* $OpenBSD: mio_rmidi.c,v 1.8 2011/04/12 21:40:22 ratchov Exp $ */ 26efede29Sratchov /* 36efede29Sratchov * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> 46efede29Sratchov * 56efede29Sratchov * Permission to use, copy, modify, and distribute this software for any 66efede29Sratchov * purpose with or without fee is hereby granted, provided that the above 76efede29Sratchov * copyright notice and this permission notice appear in all copies. 86efede29Sratchov * 96efede29Sratchov * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 106efede29Sratchov * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 116efede29Sratchov * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 126efede29Sratchov * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 136efede29Sratchov * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 146efede29Sratchov * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 156efede29Sratchov * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 166efede29Sratchov */ 176efede29Sratchov 186efede29Sratchov #include <sys/types.h> 196efede29Sratchov #include <sys/stat.h> 2032917b69Sratchov 216efede29Sratchov #include <errno.h> 226efede29Sratchov #include <fcntl.h> 2332917b69Sratchov #include <limits.h> 246efede29Sratchov #include <poll.h> 256efede29Sratchov #include <stdio.h> 266efede29Sratchov #include <stdlib.h> 276efede29Sratchov #include <string.h> 286efede29Sratchov #include <unistd.h> 296efede29Sratchov 306efede29Sratchov #include "mio_priv.h" 316efede29Sratchov 32*dd964a88Sratchov struct mio_rmidi_hdl { 336efede29Sratchov struct mio_hdl mio; 346efede29Sratchov int fd; 356efede29Sratchov }; 366efede29Sratchov 37*dd964a88Sratchov static void mio_rmidi_close(struct mio_hdl *); 38*dd964a88Sratchov static size_t mio_rmidi_read(struct mio_hdl *, void *, size_t); 39*dd964a88Sratchov static size_t mio_rmidi_write(struct mio_hdl *, const void *, size_t); 40*dd964a88Sratchov static int mio_rmidi_pollfd(struct mio_hdl *, struct pollfd *, int); 41*dd964a88Sratchov static int mio_rmidi_revents(struct mio_hdl *, struct pollfd *); 426efede29Sratchov 43*dd964a88Sratchov static struct mio_ops mio_rmidi_ops = { 44*dd964a88Sratchov mio_rmidi_close, 45*dd964a88Sratchov mio_rmidi_write, 46*dd964a88Sratchov mio_rmidi_read, 47*dd964a88Sratchov mio_rmidi_pollfd, 48*dd964a88Sratchov mio_rmidi_revents, 496efede29Sratchov }; 506efede29Sratchov 516efede29Sratchov struct mio_hdl * 52*dd964a88Sratchov mio_rmidi_open(const char *str, unsigned mode, int nbio) 536efede29Sratchov { 546efede29Sratchov int fd, flags; 55*dd964a88Sratchov struct mio_rmidi_hdl *hdl; 566efede29Sratchov char path[PATH_MAX]; 576efede29Sratchov 58*dd964a88Sratchov hdl = malloc(sizeof(struct mio_rmidi_hdl)); 596efede29Sratchov if (hdl == NULL) 606efede29Sratchov return NULL; 61*dd964a88Sratchov mio_create(&hdl->mio, &mio_rmidi_ops, mode, nbio); 626efede29Sratchov 636efede29Sratchov snprintf(path, sizeof(path), "/dev/rmidi%s", str); 646efede29Sratchov if (mode == (MIO_OUT | MIO_IN)) 656efede29Sratchov flags = O_RDWR; 666efede29Sratchov else 676efede29Sratchov flags = (mode & MIO_OUT) ? O_WRONLY : O_RDONLY; 689d75d49dSratchov if (nbio) 699d75d49dSratchov flags |= O_NONBLOCK; 709d75d49dSratchov while ((fd = open(path, flags)) < 0) { 716efede29Sratchov if (errno == EINTR) 726efede29Sratchov continue; 736efede29Sratchov DPERROR(path); 746efede29Sratchov goto bad_free; 756efede29Sratchov } 766efede29Sratchov if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { 776efede29Sratchov DPERROR("FD_CLOEXEC"); 786efede29Sratchov goto bad_close; 796efede29Sratchov } 806efede29Sratchov hdl->fd = fd; 816efede29Sratchov return (struct mio_hdl *)hdl; 826efede29Sratchov bad_close: 836efede29Sratchov while (close(hdl->fd) < 0 && errno == EINTR) 846efede29Sratchov ; /* retry */ 856efede29Sratchov bad_free: 866efede29Sratchov free(hdl); 876efede29Sratchov return NULL; 886efede29Sratchov } 896efede29Sratchov 906efede29Sratchov static void 91*dd964a88Sratchov mio_rmidi_close(struct mio_hdl *sh) 926efede29Sratchov { 93*dd964a88Sratchov struct mio_rmidi_hdl *hdl = (struct mio_rmidi_hdl *)sh; 946efede29Sratchov int rc; 956efede29Sratchov 966efede29Sratchov do { 976efede29Sratchov rc = close(hdl->fd); 986efede29Sratchov } while (rc < 0 && errno == EINTR); 996efede29Sratchov free(hdl); 1006efede29Sratchov } 1016efede29Sratchov 1026efede29Sratchov static size_t 103*dd964a88Sratchov mio_rmidi_read(struct mio_hdl *sh, void *buf, size_t len) 1046efede29Sratchov { 105*dd964a88Sratchov struct mio_rmidi_hdl *hdl = (struct mio_rmidi_hdl *)sh; 1066efede29Sratchov ssize_t n; 1076efede29Sratchov 1086efede29Sratchov while ((n = read(hdl->fd, buf, len)) < 0) { 1096efede29Sratchov if (errno == EINTR) 1106efede29Sratchov continue; 1116efede29Sratchov if (errno != EAGAIN) { 112*dd964a88Sratchov DPERROR("mio_rmidi_read: read"); 1136efede29Sratchov hdl->mio.eof = 1; 1146efede29Sratchov } 1156efede29Sratchov return 0; 1166efede29Sratchov } 1176efede29Sratchov if (n == 0) { 118*dd964a88Sratchov DPRINTF("mio_rmidi_read: eof\n"); 1196efede29Sratchov hdl->mio.eof = 1; 1206efede29Sratchov return 0; 1216efede29Sratchov } 1226efede29Sratchov return n; 1236efede29Sratchov } 1246efede29Sratchov 1256efede29Sratchov static size_t 126*dd964a88Sratchov mio_rmidi_write(struct mio_hdl *sh, const void *buf, size_t len) 1276efede29Sratchov { 128*dd964a88Sratchov struct mio_rmidi_hdl *hdl = (struct mio_rmidi_hdl *)sh; 1296efede29Sratchov ssize_t n; 1306efede29Sratchov 1316efede29Sratchov while ((n = write(hdl->fd, buf, len)) < 0) { 1326efede29Sratchov if (errno == EINTR) 1336efede29Sratchov continue; 1346efede29Sratchov if (errno != EAGAIN) { 135*dd964a88Sratchov DPERROR("mio_rmidi_write: write"); 1366efede29Sratchov hdl->mio.eof = 1; 1376efede29Sratchov } 1386efede29Sratchov return 0; 1396efede29Sratchov } 1406efede29Sratchov return n; 1416efede29Sratchov } 1426efede29Sratchov 1436efede29Sratchov static int 144*dd964a88Sratchov mio_rmidi_pollfd(struct mio_hdl *sh, struct pollfd *pfd, int events) 1456efede29Sratchov { 146*dd964a88Sratchov struct mio_rmidi_hdl *hdl = (struct mio_rmidi_hdl *)sh; 1476efede29Sratchov 1486efede29Sratchov pfd->fd = hdl->fd; 1496efede29Sratchov pfd->events = events; 1506efede29Sratchov return 1; 1516efede29Sratchov } 1526efede29Sratchov 153ee5ea84aSratchov static int 154*dd964a88Sratchov mio_rmidi_revents(struct mio_hdl *sh, struct pollfd *pfd) 1556efede29Sratchov { 1566efede29Sratchov return pfd->revents; 1576efede29Sratchov } 158