/* libcqcam - shared Color Quickcam routines * Copyright (C) 1996-1998 by Patrick Reynolds * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ // I/O ports wrapper code // This file might need tweaking if you're trying to port my code to other // x86 Unix platforms. Code is already available for Linux, FreeBSD, and // QNX; see the Makefile. // // QNX code by: Anders Arpteg // FreeBSD code by: Patrick Reynolds and Charles // Henrich //#include "config.h" #include #include #ifdef LOCKING #include #include #endif /* LOCKING */ #ifdef __linux__ #if defined(arm) || defined(__aarch64__) || defined(__hppa__) || defined(__sparc__) || defined(__ppc__) || defined(__powerpc__) || defined(__s390__) || defined(__s390x__) || defined(__mips__) || defined(__mc68000__) #include #else #include #endif /* arm */ #elif defined(QNX) #include #elif defined(__FreeBSD__) #include #include #elif defined(BSDI) #include #elif defined(OPENBSD) #include #elif defined(LYNX) #include "lynx-io.h" #elif defined(SOLARIS) #include "solaris-io.h" #else #error Please define a platform in the Makefile #endif /* which OS */ #include "port.h" port_t::port_t(int iport) { port = -1; #ifdef LOCKING if (lock(iport) == -1) { #ifdef DEBUG fprintf(stderr, "port 0x%x already locked\n", iport); #endif /* DEBUG */ return; } #endif /* LOCKING */ #ifdef LINUX #if defined(arm) || defined(__aarch64__) || defined(__hppa__) || defined(__sparc__) || defined(__ppc__) || defined(__powerpc__) || defined(__s390__) || defined(__s390x__) || defined(__mips__) || defined(__mc68000__) if ((devport = open("/dev/port", O_RDWR)) < 0) { perror("open /dev/port"); return; } #else if (ioperm(iport, 3, 1) == -1) { perror("ioperm()"); return; } #endif /* arm */ #elif defined(FREEBSD) if ((devio = fopen("/dev/io", "r+")) == NULL) { perror("fopen /dev/io"); return; } #elif defined(OPENBSD) if (i386_iopl(1) == -1) { perror("i386_iopl"); return; } #elif defined(LYNX) if (io_access() < 0) { perror("io_access"); return; } #elif defined(SOLARIS) if (openiop()) { perror("openiop"); return; } #endif /* which OS */ port = iport; port1 = port + 1; port2 = port + 2; control_reg = read_control(); } port_t::~port_t(void) { #ifdef LOCKING unlock(port); #endif /* LOCKING */ #ifdef LINUX #if defined(arm) || defined(__aarch64__) || defined(__hppa__) || defined(__sparc__) || defined(__ppc__) || defined(__powerpc__) || defined(__s390__) || defined(__s390x__) || defined(__mips__) || defined(__mc68000__) if (devport >= 0) close(devport); #else if (port > 0 && geteuid() == 0) if (ioperm(port, 3, 0) != 0) // drop port permissions -- still must // be root perror("ioperm()"); #endif /* arm */ #elif defined(FREEBSD) if (devio != NULL) fclose(devio); #elif defined(SOLARIS) close(iopfd); #endif /* which OS */ } #ifdef LOCKING int port_t::lock(int portnum) { char lockfile[80]; sprintf(lockfile, "/tmp/LOCK.qcam.0x%x", portnum); while ((lock_fd = open(lockfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == -1) { if (errno != EEXIST) { perror(lockfile); return -1; } struct stat stat_buf; if (lstat(lockfile, &stat_buf) < 0) continue; if (S_ISLNK(stat_buf.st_mode) || stat_buf.st_uid != 0) { if (unlink(lockfile)) { if (errno == ENOENT) continue; if (errno != EISDIR || (rmdir(lockfile) && errno != ENOENT)) { /* known problem: if lockfile exists and is a non-empty directory, we give up instead of doing an rm-r of it */ perror(lockfile); return -1; } } continue; } lock_fd = open(lockfile, O_WRONLY, 0600); if (lock_fd == -1) { perror(lockfile); return -1; } break; } static struct flock lock_info; lock_info.l_type = F_WRLCK; #ifdef LOCK_FAIL if (fcntl(lock_fd, F_SETLK, &lock_info) != 0) { #else if (fcntl(lock_fd, F_SETLKW, &lock_info) != 0) { #endif /* LOCK_FAIL */ if (errno != EAGAIN) perror("fcntl"); return -1; } chown(lockfile, getuid(), getgid()); #ifdef DEBUG fprintf(stderr, "Locked port 0x%x\n", portnum); #endif /* DEBUG */ return 0; } void port_t::unlock(int portnum) { if (portnum == -1) return; close(lock_fd); // this clears the lock char lockfile[80]; sprintf(lockfile, "/tmp/LOCK.qcam.0x%x", portnum); if (unlink(lockfile)) perror(lockfile); #ifdef DEBUG fprintf(stderr, "Unlocked port 0x%x\n", portnum); #endif /* DEBUG */ } #endif /* LOCKING */