summaryrefslogtreecommitdiffstats
path: root/kstars/kstars/indi/fli/libfli-sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kstars/kstars/indi/fli/libfli-sys.c')
-rw-r--r--kstars/kstars/indi/fli/libfli-sys.c481
1 files changed, 481 insertions, 0 deletions
diff --git a/kstars/kstars/indi/fli/libfli-sys.c b/kstars/kstars/indi/fli/libfli-sys.c
new file mode 100644
index 00000000..dda7462f
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-sys.c
@@ -0,0 +1,481 @@
+/*
+
+ Copyright (c) 2002 Finger Lakes Instrumentation (FLI), L.L.C.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ Neither the name of Finger Lakes Instrumentation (FLI), LLC
+ nor the names of its contributors may be used to endorse or
+ promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ ======================================================================
+
+ Finger Lakes Instrumentation, L.L.C. (FLI)
+ web: http://www.fli-cam.com
+ email: support@fli-cam.com
+
+*/
+
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <glob.h>
+
+#include "libfli-libfli.h"
+#include "libfli-debug.h"
+#include "libfli-mem.h"
+#include "libfli-camera.h"
+#include "libfli-filter-focuser.h"
+#include "libfli-sys.h"
+#include "libfli-parport.h"
+#include "libfli-usb.h"
+#include "libfli-serial.h"
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+static long unix_fli_list_parport(flidomain_t domain, char ***names);
+static long unix_fli_list_usb(flidomain_t domain, char ***names);
+static long unix_fli_list_serial(flidomain_t domain, char ***names);
+
+#ifdef __linux__
+long linux_usb_reset(flidev_t dev);
+#endif
+
+long unix_fli_connect(flidev_t dev, char *name, long domain)
+{
+ fli_unixio_t *io;
+
+ CHKDEVICE(dev);
+
+ if (name == NULL)
+ return -EINVAL;
+
+ /* Lock functions should be set before any other functions used */
+ DEVICE->fli_lock = unix_fli_lock;
+ DEVICE->fli_unlock = unix_fli_unlock;
+
+ DEVICE->domain = domain & 0x00ff;
+ DEVICE->devinfo.type = domain & 0xff00;
+
+ debug(FLIDEBUG_INFO, "Domain: 0x%04x", DEVICE->domain);
+ debug(FLIDEBUG_INFO, " Type: 0x%04x", DEVICE->devinfo.type);
+
+ if ((io = xcalloc(1, sizeof(fli_unixio_t))) == NULL)
+ return -ENOMEM;
+
+ if ((io->fd = open(name, O_RDWR)) == -1)
+ {
+ xfree(io);
+ return -errno;
+ }
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ DEVICE->fli_io = unix_parportio;
+ break;
+
+ case FLIDOMAIN_USB:
+ {
+ int r;
+
+ if( (r = unix_usbverifydescriptor(dev, io)) != 0)
+ {
+ close(io->fd);
+ xfree(io);
+ return r;
+ }
+ DEVICE->fli_io = unix_usbio;
+ }
+ break;
+
+ case FLIDOMAIN_SERIAL:
+ DEVICE->fli_io = unix_serialio;
+ break;
+
+ default:
+ close(io->fd);
+ xfree(io);
+ return -EINVAL;
+ }
+
+ switch (DEVICE->devinfo.type)
+ {
+ case FLIDEVICE_CAMERA:
+ DEVICE->fli_open = fli_camera_open;
+ DEVICE->fli_close = fli_camera_close;
+ DEVICE->fli_command = fli_camera_command;
+ break;
+
+ case FLIDEVICE_FOCUSER:
+ DEVICE->fli_open = fli_focuser_open;
+ DEVICE->fli_close = fli_focuser_close;
+ DEVICE->fli_command = fli_focuser_command;
+ break;
+
+ case FLIDEVICE_FILTERWHEEL:
+ DEVICE->fli_open = fli_filter_open;
+ DEVICE->fli_close = fli_filter_close;
+ DEVICE->fli_command = fli_filter_command;
+ break;
+
+ default:
+ close(io->fd);
+ xfree(io);
+ return -EINVAL;
+ }
+
+ DEVICE->io_data = io;
+ DEVICE->name = xstrdup(name);
+ DEVICE->io_timeout = 60 * 1000; /* 1 min. */
+
+ return 0;
+}
+
+long unix_fli_disconnect(flidev_t dev)
+{
+ int err = 0;
+ fli_unixio_t *io;
+
+ CHKDEVICE(dev);
+
+#ifdef __linux__
+ if ((DEVICE->domain & 0x00ff) == FLIDOMAIN_USB) {
+ debug(FLIDEBUG_INFO, "Resetting device");
+ linux_usb_reset(dev);
+ }
+#endif
+
+ if ((io = DEVICE->io_data) == NULL)
+ return -EINVAL;
+
+ if (close(io->fd))
+ err = -errno;
+
+ xfree(DEVICE->io_data);
+
+ DEVICE->io_data = NULL;
+ DEVICE->fli_lock = NULL;
+ DEVICE->fli_unlock = NULL;
+ DEVICE->fli_io = NULL;
+ DEVICE->fli_open = NULL;
+ DEVICE->fli_close = NULL;
+ DEVICE->fli_command = NULL;
+
+ return err;
+}
+
+#if defined(_USE_FLOCK_)
+
+long unix_fli_lock(flidev_t dev)
+{
+ fli_unixio_t *io = DEVICE->io_data;
+
+ if (io == NULL)
+ return -ENODEV;
+
+ if (flock(io->fd, LOCK_EX) == -1)
+ return -errno;
+ else
+ return 0;
+}
+
+long unix_fli_unlock(flidev_t dev)
+{
+ fli_unixio_t *io = DEVICE->io_data;
+
+ if (io == NULL)
+ return -ENODEV;
+
+ if (flock(io->fd, LOCK_UN) == -1)
+ return -errno;
+ else
+ return 0;
+}
+
+#else /* !defined(_USE_FLOCK_) */
+
+#define PUBLIC_DIR "/var/spool/uucppublic"
+
+long unix_fli_lock(flidev_t dev)
+{
+ int fd, err = 0, locked = 0, i;
+ char tmpf[] = PUBLIC_DIR "/temp.XXXXXX", lockf[PATH_MAX], name[PATH_MAX];
+ FILE *f;
+ unsigned int backoff = 10000;
+ pid_t pid;
+
+ if ((fd = mkstemp(tmpf)) == -1)
+ return -errno;
+
+ if ((f = fdopen(fd, "w")) == NULL)
+ {
+ err = -errno;
+ goto done;
+ }
+
+ fprintf(f, "%d\n", getpid());
+ fclose(f);
+
+ if (chmod(tmpf, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
+ S_IROTH | S_IWOTH) == -1)
+ {
+ err = -errno;
+ goto done;
+ }
+
+ for (i = 0; DEVICE->name[i] != '\0' && i < PATH_MAX; i++)
+ name[i] = (DEVICE->name[i] == '/') ? '-' : DEVICE->name[i];
+
+ name[MIN(i, PATH_MAX - 1)] = '\0';
+
+ if (snprintf(lockf, PATH_MAX, PUBLIC_DIR "/libfli%s.lock",
+ name) >= PATH_MAX)
+ {
+ err = -EOVERFLOW;
+ goto done;
+ }
+
+ do {
+ if (link(tmpf, lockf) == -1)
+ {
+ int r;
+
+ if (errno != EEXIST)
+ {
+ err = -errno;
+ goto done;
+ }
+
+ if ((f = fopen(lockf, "r")) == NULL)
+ continue;
+
+ r = fscanf(f, "%d\n", &pid);
+ fclose(f);
+ if (r != 1)
+ continue;
+
+ if (kill(pid, 0))
+ {
+ if (errno == ESRCH)
+ {
+ debug(FLIDEBUG_WARN, "Removing stale lock file");
+ unlink(lockf);
+ }
+
+ continue;
+ }
+ else
+ {
+ usleep(backoff);
+ if ((backoff <<= 2) == 0)
+ {
+ err = -ETIMEDOUT;
+ goto done;
+ }
+ }
+ }
+ else
+ locked = 1;
+ } while (!locked);
+
+ done:
+
+ unlink(tmpf);
+
+ return err;
+}
+
+long unix_fli_unlock(flidev_t dev)
+{
+ char lockf[PATH_MAX], name[PATH_MAX];
+ FILE *f;
+ pid_t pid = -1;
+ int i;
+
+ for (i = 0; DEVICE->name[i] != '\0' && i < PATH_MAX; i++)
+ name[i] = (DEVICE->name[i] == '/') ? '-' : DEVICE->name[i];
+
+ name[MIN(i, PATH_MAX - 1)] = '\0';
+
+ if (snprintf(lockf, PATH_MAX, PUBLIC_DIR "/libfli%s.lock",
+ name) >= PATH_MAX)
+ return -EOVERFLOW;
+
+ if ((f = fopen(lockf, "r")) == NULL)
+ {
+ debug(FLIDEBUG_WARN, "Trying to unlock `%s' when not locked",
+ DEVICE->name);
+ return -errno;
+ }
+
+ if (fscanf(f, "%d\n", &pid) != 1)
+ debug(FLIDEBUG_WARN, "Invalid lock file for `%s'", DEVICE->name);
+
+ fclose(f);
+
+ if (pid != -1 && pid != getpid())
+ debug(FLIDEBUG_WARN, "Forcing unlock of `%s' from process %d",
+ DEVICE->name, pid);
+
+ unlink(lockf);
+
+ return 0;
+}
+
+#undef PUBLIC_DIR
+
+#endif /* defined(_USE_FLOCK_) */
+
+long unix_fli_list(flidomain_t domain, char ***names)
+{
+ *names = NULL;
+
+ switch (domain & 0x00ff)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ return unix_fli_list_parport(domain, names);
+ break;
+
+ case FLIDOMAIN_USB:
+ return unix_fli_list_usb(domain, names);
+ break;
+
+ case FLIDOMAIN_SERIAL:
+ return unix_fli_list_serial(domain, names);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* Not reached */
+ return -EINVAL;
+}
+
+static long unix_fli_list_glob(char *pattern, flidomain_t domain,
+ char ***names)
+{
+ int retval, i, found = 0;
+ char **list;
+ glob_t g;
+
+ if ((retval = glob(pattern, 0, NULL, &g)))
+ {
+#ifdef GLOB_NOMATCH
+ if (retval != GLOB_NOMATCH)
+ {
+ globfree(&g);
+ return -errno;
+ }
+
+ /* retval == GLOB_NOMATCH */
+ g.gl_pathc = 0;
+#else
+ globfree(&g);
+ return -errno;
+#endif
+ }
+
+ if ((list = xmalloc((g.gl_pathc + 1) * sizeof(char *))) == NULL)
+ {
+ globfree(&g);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < (int) g.gl_pathc; i++)
+ {
+ flidev_t dev;
+
+ if (FLIOpen(&dev, g.gl_pathv[i], domain))
+ continue;
+
+ if ((list[found] = xmalloc(strlen(g.gl_pathv[i]) +
+ strlen(DEVICE->devinfo.model) + 2)) == NULL)
+ {
+ int j;
+
+ FLIClose(dev);
+ for (j = 0; j < found; j++)
+ xfree(list[j]);
+ xfree(list);
+ globfree(&g);
+ return -ENOMEM;
+ }
+
+ sprintf(list[found], "%s;%s", g.gl_pathv[i], DEVICE->devinfo.model);
+ FLIClose(dev);
+ found++;
+ }
+
+ globfree(&g);
+
+ /* Terminate the list */
+ list[found++] = NULL;
+
+ list = xrealloc(list, found * sizeof(char *));
+ *names = list;
+
+ return 0;
+}
+
+#ifdef __linux__
+
+static long unix_fli_list_parport(flidomain_t domain, char ***names)
+{
+ return unix_fli_list_glob(PARPORT_GLOB, domain, names);
+}
+
+#else
+
+static long unix_fli_list_parport(flidomain_t domain, char ***names)
+{
+ return -EINVAL;
+}
+
+#endif
+
+static long unix_fli_list_usb(flidomain_t domain, char ***names)
+{
+ return unix_fli_list_glob(USB_GLOB, domain, names);
+}
+
+static long unix_fli_list_serial(flidomain_t domain, char ***names)
+{
+ return unix_fli_list_glob(SERIAL_GLOB, domain, names);
+}