summaryrefslogtreecommitdiffstats
path: root/kstars/kstars/indi/fli
diff options
context:
space:
mode:
Diffstat (limited to 'kstars/kstars/indi/fli')
-rw-r--r--kstars/kstars/indi/fli/Makefile.am24
-rw-r--r--kstars/kstars/indi/fli/fli_ioctl.h119
-rw-r--r--kstars/kstars/indi/fli/libfli-camera-parport.c753
-rw-r--r--kstars/kstars/indi/fli/libfli-camera-parport.h102
-rw-r--r--kstars/kstars/indi/fli/libfli-camera-usb.c776
-rw-r--r--kstars/kstars/indi/fli/libfli-camera-usb.h98
-rw-r--r--kstars/kstars/indi/fli/libfli-camera.c790
-rw-r--r--kstars/kstars/indi/fli/libfli-camera.h111
-rw-r--r--kstars/kstars/indi/fli/libfli-debug.c120
-rw-r--r--kstars/kstars/indi/fli/libfli-debug.h53
-rw-r--r--kstars/kstars/indi/fli/libfli-filter-focuser.c625
-rw-r--r--kstars/kstars/indi/fli/libfli-filter-focuser.h74
-rw-r--r--kstars/kstars/indi/fli/libfli-libfli.h199
-rw-r--r--kstars/kstars/indi/fli/libfli-mem.c203
-rw-r--r--kstars/kstars/indi/fli/libfli-mem.h54
-rw-r--r--kstars/kstars/indi/fli/libfli-parport.c136
-rw-r--r--kstars/kstars/indi/fli/libfli-parport.h64
-rw-r--r--kstars/kstars/indi/fli/libfli-serial.c189
-rw-r--r--kstars/kstars/indi/fli/libfli-serial.h51
-rw-r--r--kstars/kstars/indi/fli/libfli-sys.c481
-rw-r--r--kstars/kstars/indi/fli/libfli-sys.h108
-rw-r--r--kstars/kstars/indi/fli/libfli-usb-sys-bsd.c133
-rw-r--r--kstars/kstars/indi/fli/libfli-usb-sys-linux.c225
-rw-r--r--kstars/kstars/indi/fli/libfli-usb-sys-null.c67
-rw-r--r--kstars/kstars/indi/fli/libfli-usb.c94
-rw-r--r--kstars/kstars/indi/fli/libfli-usb.h69
-rw-r--r--kstars/kstars/indi/fli/libfli.c1383
-rw-r--r--kstars/kstars/indi/fli/libfli.h214
-rw-r--r--kstars/kstars/indi/fli/libfli.pdfbin0 -> 110777 bytes
-rw-r--r--kstars/kstars/indi/fli/readme.txt15
30 files changed, 7330 insertions, 0 deletions
diff --git a/kstars/kstars/indi/fli/Makefile.am b/kstars/kstars/indi/fli/Makefile.am
new file mode 100644
index 00000000..859b459e
--- /dev/null
+++ b/kstars/kstars/indi/fli/Makefile.am
@@ -0,0 +1,24 @@
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+if LINUX
+libfli_linux = libfli_linux.la
+endif
+
+if BSD
+libfli_bsd = libfli_bsd.la
+endif
+
+if NULL
+libfli_null = libfli_null.la
+endif
+
+noinst_LTLIBRARIES = libfli.la $(libfli_linux) $(libfli_bsd) $(libfli_null)
+
+libfli_linux_la_SOURCES = libfli-parport.c libfli-usb-sys-linux.c
+libfli_bsd_la_SOURCES = libfli-usb-sys-bsd.c
+libfli_null_la_SOURCES = libfli-usb-sys-null.c
+
+libfli_la_SOURCES = libfli.c libfli-camera.c libfli-camera-parport.c libfli-camera-usb.c libfli-filter-focuser.c libfli-mem.c libfli-serial.c libfli-sys.c libfli-usb.c libfli-debug.c
+AM_LDFLAGS = $(all_libraries)
+libfli_la_LIBADD = $(libfli_linux) $(libfli_bsd) $(libfli_null)
diff --git a/kstars/kstars/indi/fli/fli_ioctl.h b/kstars/kstars/indi/fli/fli_ioctl.h
new file mode 100644
index 00000000..63dae274
--- /dev/null
+++ b/kstars/kstars/indi/fli/fli_ioctl.h
@@ -0,0 +1,119 @@
+/*
+
+ Copyright (c) 2000 Finger Lakes Instrumentation (FLI), LLC.
+ 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 (FLI)
+ web: http://www.fli-cam.com
+ email: fli@rpa.net
+
+*/
+
+#ifndef _FLI_IOCTL_H
+#define _FLI_IOCTL_H
+
+#include <asm/ioctl.h>
+
+/* 8-bit special value to identify ioctl 'type' */
+#define FLI_IOCTL_TYPE 'F'
+
+/* Macros declaring ioctl commands and the variables they operate on */
+#define FLI_IOCTL_MISC_CMDS \
+ FLI_IOCTL_CMD(FLI_RESET_PORT_VALUES, **NONE**) \
+ FLI_IOCTL_CMD(FLI_LOCK_PORT, **NONE**) \
+ FLI_IOCTL_CMD(FLI_UNLOCK_PORT, **NONE**)
+
+#define FLI_IOCTL_SPECIAL_SET_CMDS \
+ FLI_IOCTL_CMD(FLI_SET_DMABUFFSIZE, dmabuffsize)
+
+#define FLI_IOCTL_SET_CMDS \
+ FLI_IOCTL_CMD(FLI_SET_DMATHRESH, dmathresh) \
+ FLI_IOCTL_CMD(FLI_SET_DTO, dto) \
+ FLI_IOCTL_CMD(FLI_SET_RTO, rto) \
+ FLI_IOCTL_CMD(FLI_SET_WTO, wto) \
+ FLI_IOCTL_CMD(FLI_SET_LTL, ltl) \
+ FLI_IOCTL_CMD(FLI_SET_DIR, dir) \
+ FLI_IOCTL_CMD(FLI_SET_NUMREAD, numread) \
+ FLI_IOCTL_CMD(FLI_SET_NUMWRITE, numwrite) \
+ FLI_IOCTL_CMD(FLI_SET_NUMDTO, numdto) \
+ FLI_IOCTL_CMD(FLI_SET_NUMRTO, numrto) \
+ FLI_IOCTL_CMD(FLI_SET_NUMWTO, numwto)
+
+#define FLI_IOCTL_GET_CMDS \
+ FLI_IOCTL_CMD(FLI_GET_DMABUFFSIZE, dmabuffsize) \
+ FLI_IOCTL_CMD(FLI_GET_DMATHRESH, dmathresh) \
+ FLI_IOCTL_CMD(FLI_GET_DTO, dto) \
+ FLI_IOCTL_CMD(FLI_GET_RTO, rto) \
+ FLI_IOCTL_CMD(FLI_GET_WTO, wto) \
+ FLI_IOCTL_CMD(FLI_GET_DIR, dir) \
+ FLI_IOCTL_CMD(FLI_GET_LTL, ltl) \
+ FLI_IOCTL_CMD(FLI_GET_NUMREAD, numread) \
+ FLI_IOCTL_CMD(FLI_GET_NUMWRITE, numwrite) \
+ FLI_IOCTL_CMD(FLI_GET_NUMDTO, numdto) \
+ FLI_IOCTL_CMD(FLI_GET_NUMRTO, numrto) \
+ FLI_IOCTL_CMD(FLI_GET_NUMWTO, numwto)
+
+/* Enumerate ioctl numbers */
+#undef FLI_SET_CMD
+#define FLI_IOCTL_CMD(cmd, var) cmd##_NUM,
+
+enum {
+ FLI_IOCTL_MISC_CMDS
+ FLI_IOCTL_SPECIAL_SET_CMDS
+ FLI_IOCTL_SET_CMDS
+ FLI_IOCTL_GET_CMDS
+};
+
+/* Enumerate the actual ioctl commands */
+#undef FLI_IOCTL_CMD
+#define FLI_IOCTL_CMD(cmd, var) \
+ enum {cmd = _IO(FLI_IOCTL_TYPE, cmd##_NUM)};
+
+FLI_IOCTL_MISC_CMDS;
+
+#undef FLI_IOCTL_CMD
+#define FLI_IOCTL_CMD(cmd, var) \
+ enum {cmd = _IOW(FLI_IOCTL_TYPE, cmd##_NUM, int)};
+
+FLI_IOCTL_SPECIAL_SET_CMDS;
+FLI_IOCTL_SET_CMDS;
+
+#undef FLI_IOCTL_CMD
+#define FLI_IOCTL_CMD(cmd, var ) \
+ enum {cmd = _IOR(FLI_IOCTL_TYPE, cmd##_NUM, int)};
+
+FLI_IOCTL_GET_CMDS;
+
+#endif /* _FLI_IOCTL_H */
diff --git a/kstars/kstars/indi/fli/libfli-camera-parport.c b/kstars/kstars/indi/fli/libfli-camera-parport.c
new file mode 100644
index 00000000..bd5343ce
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-camera-parport.c
@@ -0,0 +1,753 @@
+/*
+
+ 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
+
+*/
+
+#ifdef WIN32
+#include <winsock.h>
+#else
+#include <sys/param.h>
+#include <netinet/in.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "libfli-libfli.h"
+#include "libfli-mem.h"
+#include "libfli-debug.h"
+#include "libfli-camera.h"
+#include "libfli-camera-parport.h"
+
+long fli_camera_parport_open(flidev_t dev)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf;
+ int id;
+
+ cam = DEVICE->device_data;
+
+ /* Set timeout values */
+ cam->readto = 1000;
+ cam->writeto = 1000;
+ cam->dirto = 1000;
+
+ rlen = 2;
+ wlen = 2;
+ buf = htons(C_ADDRESS(1, EPARAM_ECHO));
+ IO(dev, &buf, &wlen, &rlen);
+ if (buf != htons(C_ADDRESS(1, EPARAM_ECHO)))
+ {
+ debug(FLIDEBUG_FAIL, "Echo back from camera failed.");
+ return -EIO;
+ }
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_ADDRESS(1, EPARAM_DEVICE));
+ IO(dev, &buf, &wlen, &rlen);
+ DEVICE->devinfo.hwrev = ntohs(buf) & 0x00ff;
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_ADDRESS(1, EPARAM_CCDID));
+ IO(dev, &buf, &wlen, &rlen);
+ DEVICE->devinfo.devid = ntohs(buf) & 0x00ff;
+
+ for (id = 0; knowndev[id].index != 0; id++)
+ if (knowndev[id].index == DEVICE->devinfo.devid)
+ break;
+
+ if (knowndev[id].index == 0)
+ return -ENODEV;
+
+ cam->ccd.array_area.ul.x = knowndev[id].array_area.ul.x;
+ cam->ccd.array_area.ul.y = knowndev[id].array_area.ul.y;
+ cam->ccd.array_area.lr.x = knowndev[id].array_area.lr.x;
+ cam->ccd.array_area.lr.y = knowndev[id].array_area.lr.y;
+ cam->ccd.visible_area.ul.x = knowndev[id].visible_area.ul.x;
+ cam->ccd.visible_area.ul.y = knowndev[id].visible_area.ul.y;
+ cam->ccd.visible_area.lr.x = knowndev[id].visible_area.lr.x;
+ cam->ccd.visible_area.lr.y = knowndev[id].visible_area.lr.y;
+ cam->ccd.pixelwidth = knowndev[id].pixelwidth;
+ cam->ccd.pixelheight = knowndev[id].pixelheight;
+
+ if ((DEVICE->devinfo.model =
+ (char *)xmalloc(strlen(knowndev[id].model) + 1)) == NULL)
+ return -ENOMEM;
+ strcpy(DEVICE->devinfo.model, knowndev[id].model);
+
+ debug(FLIDEBUG_INFO, " Name: %s", DEVICE->devinfo.devnam);
+ debug(FLIDEBUG_INFO, " Array: (%4d,%4d),(%4d,%4d)",
+ cam->ccd.array_area.ul.x,
+ cam->ccd.array_area.ul.y,
+ cam->ccd.array_area.lr.x,
+ cam->ccd.array_area.lr.y);
+ debug(FLIDEBUG_INFO, " Visible: (%4d,%4d),(%4d,%4d)",
+ cam->ccd.visible_area.ul.x,
+ cam->ccd.visible_area.ul.y,
+ cam->ccd.visible_area.lr.x,
+ cam->ccd.visible_area.lr.y);
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_ADDRESS(1, EPARAM_SNHIGH));
+ IO(dev, &buf, &wlen, &rlen);
+ DEVICE->devinfo.serno = (ntohs(buf) & 0x00ff) << 8;
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_ADDRESS(1, EPARAM_SNLOW));
+ IO(dev, &buf, &wlen, &rlen);
+ DEVICE->devinfo.serno |= (ntohs(buf) & 0x00ff);
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_ADDRESS(1, EPARAM_FIRM));
+ IO(dev, &buf, &wlen, &rlen);
+ DEVICE->devinfo.fwrev = (ntohs(buf) & 0x00ff);
+
+ /* Initialize all varaibles to something */
+ switch(DEVICE->devinfo.hwrev)
+ {
+ case 0x01:
+ cam->tempslope = (100.0 / 201.1);
+ cam->tempintercept = (-61.613);
+ break;
+
+ case 0x02:
+ cam->tempslope = (70.0 / 215.75);
+ cam->tempintercept = (-52.5681);
+ break;
+
+ default:
+ debug(FLIDEBUG_WARN, "Could not set temperature parameters.");
+ break;
+ }
+
+ cam->vflushbin = 4;
+ cam->hflushbin = 4;
+ cam->vbin = 1;
+ cam->hbin = 1;
+ cam->image_area.ul.x = cam->ccd.visible_area.ul.x;
+ cam->image_area.ul.y = cam->ccd.visible_area.ul.y;
+ cam->image_area.lr.x = cam->ccd.visible_area.lr.x;
+ cam->image_area.lr.y = cam->ccd.visible_area.lr.y;
+ cam->exposure = 100;
+ cam->frametype = FLI_FRAME_TYPE_NORMAL;
+ cam->flushes = 0;
+ cam->bitdepth = FLI_MODE_16BIT;
+ cam->exttrigger = 0;
+
+ cam->grabrowwidth =
+ (cam->image_area.lr.x - cam->image_area.ul.x) / cam->hbin;
+ cam->grabrowcount = 1;
+ cam->grabrowcounttot = cam->grabrowcount;
+ cam->grabrowindex = 0;
+ cam->grabrowbatchsize = 1;
+ cam->grabrowbufferindex = cam->grabrowcount;
+ cam->flushcountbeforefirstrow = 0;
+ cam->flushcountafterlastrow = 0;
+
+ return 0;
+}
+
+long fli_camera_parport_get_array_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ *ul_x = cam->ccd.array_area.ul.x;
+ *ul_y = cam->ccd.array_area.ul.y;
+ *lr_x = cam->ccd.array_area.lr.x;
+ *lr_y = cam->ccd.array_area.lr.y;
+
+ return 0;
+}
+
+long fli_camera_parport_get_visible_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ *ul_x = cam->ccd.visible_area.ul.x;
+ *ul_y = cam->ccd.visible_area.ul.y;
+ *lr_x = cam->ccd.visible_area.lr.x;
+ *lr_y = cam->ccd.visible_area.lr.y;
+
+ return 0;
+}
+
+long fli_camera_parport_set_exposure_time(flidev_t dev, long exptime)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if (exptime < 0)
+ return -EINVAL;
+
+ cam->exposure = exptime;
+
+ if (exptime <= 15000) /* Less than thirty seconds..., 8.192e-3 sec */
+ {
+ cam->expdur = 1;
+ cam->expmul = (long) (((double) exptime) / 8.192);
+ }
+ else if (exptime <= 2000000) /* Less than one hour */
+ {
+ cam->expdur = (long) (1.0 / 8.192e-3);
+ cam->expmul = (long) (exptime / 1000);
+ }
+ else
+ {
+ cam->expdur = (long) (10.0 / 8.192e-3);
+ cam->expmul = (long) (exptime / 10000);
+ }
+
+ return 0;
+}
+
+long fli_camera_parport_set_image_area(flidev_t dev, long ul_x, long ul_y,
+ long lr_x, long lr_y)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if ((ul_x < cam->ccd.visible_area.ul.x) ||
+ (ul_y < cam->ccd.visible_area.ul.y) ||
+ (lr_x > cam->ccd.visible_area.lr.x) ||
+ (lr_y > cam->ccd.visible_area.lr.y))
+ return -EINVAL;
+
+ cam->image_area.ul.x = ul_x;
+ cam->image_area.ul.y = ul_y;
+ cam->image_area.lr.x = lr_x;
+ cam->image_area.lr.y = lr_y;
+
+ return 0;
+}
+
+long fli_camera_parport_set_hbin(flidev_t dev, long hbin)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if ((hbin < 1) || (hbin > 16))
+ return -EINVAL;
+
+ cam->hbin = hbin;
+ return 0;
+}
+
+long fli_camera_parport_set_vbin(flidev_t dev, long vbin)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if ((vbin < 1) || (vbin > 16))
+ return -EINVAL;
+
+ cam->vbin = vbin;
+ return 0;
+}
+
+long fli_camera_parport_get_exposure_status(flidev_t dev, long *timeleft)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf;
+
+ cam = DEVICE->device_data;
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_SHUTTER(1,0));
+ IO(dev, &buf, &wlen, &rlen);
+ if ((ntohs(buf) & 0xf000) != C_SHUTTER(0,0))
+ {
+ debug(FLIDEBUG_FAIL, "(exposurestatus) echo back from camera failed.");
+ return -EIO;
+ }
+
+ *timeleft = (long)((double)(ntohs(buf) & 0x07ff) *
+ ((double)cam->expdur * 8.192));
+
+ return 0;
+}
+
+long fli_camera_parport_set_temperature(flidev_t dev, double temperature)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf;
+
+ cam = DEVICE->device_data;
+
+ rlen = 2; wlen = 2;
+ buf = (unsigned short)((temperature - cam->tempintercept) /
+ cam->tempslope);
+ buf = htons((unsigned short) C_TEMP(buf));
+ IO(dev, &buf, &wlen, &rlen);
+ if ((ntohs(buf) & 0xf000) != C_TEMP(0))
+ {
+ debug(FLIDEBUG_FAIL, "(settemperature) echo back from camera failed.");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+long fli_camera_parport_get_temperature(flidev_t dev, double *temperature)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf;
+
+ cam = DEVICE->device_data;
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_TEMP(0x0800));
+ IO(dev, &buf, &wlen, &rlen);
+ if ((ntohs(buf) & 0xf000) != C_TEMP(0))
+ {
+ debug(FLIDEBUG_FAIL, "(settemperature) echo back from camera failed.");
+ return -EIO;
+ }
+ *temperature = cam->tempslope * (double)(ntohs(buf) & 0x00ff) +
+ cam->tempintercept;
+
+ return 0;
+}
+
+long fli_camera_parport_grab_row(flidev_t dev, void *buff, size_t width)
+{
+ flicamdata_t *cam;
+ long r;
+ double dTm;
+ long rlen, wlen;
+ unsigned short buf;
+
+ cam = DEVICE->device_data;
+
+ if (cam->flushcountbeforefirstrow > 0)
+ {
+ if ((r = fli_camera_parport_flush_rows(dev,
+ cam->flushcountbeforefirstrow, 1)))
+ return r;
+
+ cam->flushcountbeforefirstrow = 0;
+ }
+
+ dTm = (25.0e-6) * cam->ccd.array_area.lr.x + 1e-3;
+ dTm = dTm / 1e-6;
+ cam->readto = (long)dTm;
+ cam->writeto = (long)dTm;
+
+ rlen = 0; wlen = 2;
+ buf = htons((unsigned short) C_SEND(cam->grabrowwidth));
+ IO(dev, &buf, &wlen, &rlen);
+
+ if (cam->bitdepth == FLI_MODE_8BIT)
+ {
+ unsigned char *cbuf;
+ int x;
+
+ if ((cbuf = xmalloc(cam->grabrowwidth)) == NULL)
+ {
+ debug(FLIDEBUG_FAIL, "Failed memory allocation during row grab.");
+ return -ENOMEM;
+ }
+
+ rlen = cam->grabrowwidth; wlen = 0;
+ r = DEVICE->fli_io(dev, cbuf, &wlen, &rlen);
+ if (r != 0)
+ {
+ debug(FLIDEBUG_WARN, "Couldn't grab entire row, got %d of %d bytes.",
+ rlen, cam->grabrowwidth);
+ }
+ for (x = 0; x < (int)width; x++)
+ {
+ ((char *)buff)[x] = (((cbuf[x]) + 128) & 0x00ff);
+ }
+ xfree(cbuf);
+ }
+ else
+ {
+ unsigned short *sbuf;
+ int x;
+
+ if ((sbuf = xmalloc(cam->grabrowwidth * sizeof(unsigned short))) == NULL)
+ {
+ debug(FLIDEBUG_FAIL, "Failed memory allocation during row grab.");
+ return -ENOMEM;
+ }
+
+ rlen = cam->grabrowwidth * sizeof(unsigned short); wlen = 0;
+ r = DEVICE->fli_io(dev, sbuf, &wlen, &rlen);
+ if (r != 0)
+ {
+ debug(FLIDEBUG_WARN, "Couldn't grab entire row, got %d of %d bytes.",
+ rlen, cam->grabrowwidth);
+ }
+ for (x = 0; x < (int)width; x++)
+ {
+ if (DEVICE->devinfo.hwrev == 0x01) /* IMG camera */
+ {
+ ((unsigned short *)buff)[x] = ntohs(sbuf[x]) + 32768;
+ }
+ else
+ {
+ ((unsigned short *)buff)[x] = ntohs(sbuf[x]);
+ }
+ }
+ xfree(sbuf);
+ }
+
+ rlen = 2; wlen = 0;
+ IO(dev, &buf, &wlen, &rlen);
+ if (ntohs(buf) != C_SEND(width))
+ {
+ debug(FLIDEBUG_WARN, "Width: %d, requested %d.",
+ width, cam->grabrowwidth * sizeof(unsigned short));
+ debug(FLIDEBUG_WARN, "Got 0x%04x instead of 0x%04x.", ntohs(buf), C_SEND(width));
+ debug(FLIDEBUG_WARN, "Didn't get command echo at end of row.");
+ }
+
+ if (cam->grabrowcount > 0)
+ {
+ cam->grabrowcount--;
+ if (cam->grabrowcount == 0)
+ {
+ if ((r = fli_camera_parport_flush_rows(dev,
+ cam->flushcountafterlastrow, 1)))
+ return r;
+
+ cam->flushcountafterlastrow = 0;
+ cam->grabrowbatchsize = 1;
+ }
+ }
+
+ cam->readto = 1000;
+ cam->writeto = 1000;
+
+ return 0;
+}
+
+long fli_camera_parport_expose_frame(flidev_t dev)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf;
+
+ cam = DEVICE->device_data;
+
+ debug(FLIDEBUG_INFO, "Setting X Row Offset.");
+ rlen = 2; wlen = 2;
+ buf = htons((unsigned short) D_XROWOFF(cam->image_area.ul.x));
+ IO(dev, &buf, &wlen, &rlen);
+
+ debug(FLIDEBUG_INFO, "Setting X Row Width to %d.", cam->ccd.array_area.lr.x - cam->ccd.array_area.ul.x);
+ buf = htons((unsigned short) D_XROWWID(cam->ccd.array_area.lr.x - cam->ccd.array_area.ul.x));
+ IO(dev, &buf, &wlen, &rlen);
+
+ debug(FLIDEBUG_INFO, "Setting X Flush Bin.");
+ buf = htons((unsigned short) D_XFLBIN(cam->hflushbin));
+ IO(dev, &buf, &wlen, &rlen);
+
+ debug(FLIDEBUG_INFO, "Setting Y Flush Bin.");
+ buf = htons((unsigned short) D_YFLBIN(cam->vflushbin));
+ IO(dev, &buf, &wlen, &rlen);
+
+ debug(FLIDEBUG_INFO, "Setting X Bin.");
+ buf = htons((unsigned short) D_XBIN(cam->hbin));
+ IO(dev, &buf, &wlen, &rlen);
+
+ debug(FLIDEBUG_INFO, "Setting Y Bin.");
+ buf = htons((unsigned short) D_YBIN(cam->vbin));
+ IO(dev, &buf, &wlen, &rlen);
+
+ debug(FLIDEBUG_INFO, "Setting Exposure Duration.");
+ buf = htons((unsigned short) D_EXPDUR(cam->expdur));
+ IO(dev, &buf, &wlen, &rlen);
+
+ if (cam->bitdepth == FLI_MODE_8BIT)
+ {
+ debug(FLIDEBUG_INFO, "Eight Bit.");
+ buf = htons((unsigned short)((cam->exttrigger > 0) ?
+ C_RESTCFG(0,0,1,7) : C_RESTCFG(0,0,0,7)));
+ }
+ else
+ {
+ debug(FLIDEBUG_INFO, "Sixteen Bit.");
+ buf = htons((unsigned short)((cam->exttrigger > 0) ?
+ C_RESTCFG(0,0,1,15) :
+ C_RESTCFG(0,0,0,15)));
+ }
+ IO(dev, &buf, &wlen, &rlen);
+
+ if (cam->flushes > 0)
+ {
+ int r;
+
+ debug(FLIDEBUG_INFO, "Flushing array.");
+ if ((r = fli_camera_parport_flush_rows(dev,
+ cam->ccd.array_area.lr.y - cam->ccd.array_area.ul.y,
+ cam->flushes)))
+ return r;
+ }
+
+ debug(FLIDEBUG_INFO, "Exposing.");
+ buf = htons((unsigned short) C_SHUTTER((cam->frametype == FLI_FRAME_TYPE_DARK)?0:1,
+ cam->expmul));
+ IO(dev, &buf, &wlen, &rlen);
+
+ cam->grabrowwidth = cam->image_area.lr.x - cam->image_area.ul.x;
+ cam->flushcountbeforefirstrow = cam->image_area.ul.y;
+ cam->flushcountafterlastrow =
+ (cam->ccd.array_area.lr.y - cam->ccd.array_area.ul.y) -
+ ((cam->image_area.lr.y - cam->image_area.ul.y) * cam->vbin) -
+ cam->image_area.ul.y;
+
+ if (cam->flushcountafterlastrow < 0)
+ cam->flushcountafterlastrow = 0;
+
+ cam->grabrowcount = cam->image_area.lr.y - cam->image_area.ul.y;
+
+ return 0;
+}
+
+long fli_camera_parport_flush_rows(flidev_t dev, long rows, long repeat)
+{
+ flicamdata_t *cam;
+ double dTm;
+ long rlen, wlen;
+ unsigned short buf;
+
+ if (rows < 0)
+ return -EINVAL;
+
+ if (rows == 0)
+ return 0;
+
+ cam = DEVICE->device_data;
+
+ dTm = ((25e-6) / (cam->hflushbin / 2)) * cam->ccd.array_area.lr.x + 1e-3;
+ dTm = dTm * rows;
+ dTm = dTm / 1e-6;
+ cam->readto = (long)dTm;
+ cam->writeto = (long)dTm;
+
+ while (repeat>0)
+ {
+ long retval;
+
+ rlen = 2; wlen = 2;
+ buf = htons((unsigned short) C_FLUSH(rows));
+ retval = DEVICE->fli_io(dev, &buf, &wlen, &rlen);
+ if (retval != 0)
+ {
+ cam->readto = 1000;
+ cam->writeto = 1000;
+ return retval;
+ }
+ repeat--;
+ }
+
+ return 0;
+}
+
+long fli_camera_parport_set_bit_depth(flidev_t dev, flibitdepth_t bitdepth)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if (DEVICE->devinfo.type != 0x01) /* IMG cameras only support this */
+ return -EINVAL;
+
+ if ((bitdepth != FLI_MODE_8BIT) && (bitdepth != FLI_MODE_16BIT))
+ {
+ debug(FLIDEBUG_FAIL, "Invalid bit depth setting.");
+ return -EINVAL;
+ }
+
+ cam->bitdepth = bitdepth;
+
+ return 0;
+}
+
+static void correctioportdatawrite(flidev_t dev, unsigned short *Data)
+{
+ unsigned short data;
+
+ data = 0;
+
+ switch(DEVICE->devinfo.hwrev)
+ {
+ case 0x01:
+ data |= (*Data & FLICCD_IO_P0)?0x01:0;
+ data |= (*Data & FLICCD_IO_P1)?0x02:0;
+ data |= (*Data & FLICCD_IO_P2)?0x04:0;
+ data |= (*Data & FLICCD_IO_P3)?0x80:0;
+ break;
+
+ case 0x02:
+ data |= (*Data & FLICCD_IO_P0)?0x08:0;
+ data |= (*Data & FLICCD_IO_P1)?0x10:0;
+ data |= (*Data & FLICCD_IO_P2)?0x20:0;
+ data |= (*Data & FLICCD_IO_P3)?0x40:0;
+ break;
+
+ default:
+ break;
+ }
+
+ *Data = data;
+
+ return;
+}
+
+static void correctioportdataread(flidev_t dev, unsigned short *Data)
+{
+ unsigned short data;
+
+ data = 0;
+
+ switch (DEVICE->devinfo.hwrev)
+ {
+ case 0x01:
+ data |= (*Data & 0x01)?FLICCD_IO_P0:0;
+ data |= (*Data & 0x02)?FLICCD_IO_P1:0;
+ data |= (*Data & 0x04)?FLICCD_IO_P2:0;
+ data |= (*Data & 0x80)?FLICCD_IO_P3:0;
+ break;
+
+ case 0x02:
+ data |= (*Data & 0x08)?FLICCD_IO_P0:0;
+ data |= (*Data & 0x10)?FLICCD_IO_P1:0;
+ data |= (*Data & 0x20)?FLICCD_IO_P2:0;
+ data |= (*Data & 0x40)?FLICCD_IO_P3:0;
+ break;
+
+ default:
+ break;
+ }
+
+ *Data = data;
+
+ return;
+}
+
+long fli_camera_parport_read_ioport(flidev_t dev, long *ioportset)
+{
+ long rlen, wlen;
+ unsigned short buf;
+
+ rlen = 2; wlen = 2;
+ buf = htons(0x7900);
+ IO(dev, &buf, &wlen, &rlen);
+
+ *ioportset = ntohs(buf) & 0x00ff;
+ correctioportdataread(dev, (unsigned short *) ioportset);
+
+ return 0;
+}
+
+long fli_camera_parport_write_ioport(flidev_t dev, long ioportset)
+{
+ long rlen, wlen;
+ unsigned short buf = (unsigned short) ioportset;
+
+ correctioportdatawrite(dev, &buf);
+ buf = htons((unsigned short) (0x7100 | (buf & 0x00ff)));
+
+ rlen = 2; wlen = 2;
+ IO(dev, &buf, &wlen, &rlen);
+
+ return 0;
+}
+
+long fli_camera_parport_configure_ioport(flidev_t dev, long ioportset)
+{
+ long rlen, wlen;
+ unsigned short buf = (unsigned short) ioportset;
+
+ correctioportdatawrite(dev, &buf);
+ buf = htons((unsigned short) (0x7000 | (buf & 0x00ff)));
+
+ rlen = 2; wlen = 2;
+ IO(dev, &buf, &wlen, &rlen);
+
+ return 0;
+}
+
+long fli_camera_parport_control_shutter(flidev_t dev, long shutter)
+{
+ long rlen, wlen;
+ unsigned short buf;
+
+ rlen = 2; wlen = 2;
+ buf = htons(D_EXPDUR(0));
+ IO(dev, &buf, &wlen, &rlen);
+
+ switch (shutter)
+ {
+ case FLI_SHUTTER_CLOSE:
+ debug(FLIDEBUG_INFO, "Closing shutter.");
+ buf = htons(C_SHUTTER(0, 0));
+ IO(dev, &buf, &wlen, &rlen);
+ break;
+
+ case FLI_SHUTTER_OPEN:
+ buf = htons(C_SHUTTER(1, 1));
+ IO(dev, &buf, &wlen, &rlen);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/kstars/kstars/indi/fli/libfli-camera-parport.h b/kstars/kstars/indi/fli/libfli-camera-parport.h
new file mode 100644
index 00000000..12745098
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-camera-parport.h
@@ -0,0 +1,102 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_CAMERA_PARPORT_H_
+#define _LIBFLI_CAMERA_PARPORT_H_
+
+/* Define command and data word formats */
+#define C_ADDRESS(addr,ext) (0x8000|(((addr)<<8)&0x0f00)|((ext)&0x00ff))
+#define C_RESTCFG(gain,chnl,exttrig,res) (0x9000|(((gain)<<8)&0x0f00)|(((chnl)<<5)&0x00e0)|(((exttrig)<<4)&0x0010)|(((res)&0x000f)))
+#define C_SHUTTER(open,dmult) (0xa000|((dmult)&0x07ff)|(((open)<<11)&0x0800))
+#define C_SEND(x) (0xb000|((x)&0x0fff))
+#define C_FLUSH(x) (0xc000|((x)&0x0fff))
+#define C_VSKIP(x) (0xd000|((x)&0x0fff))
+#define C_HSKIP(x) (0xe000|((x)&0x0fff))
+#define C_TEMP(x) (0xf000|((x)&0x0fff))
+#define D_XROWOFF(x) (0x0000|((x)&0x0fff))
+#define D_XROWWID(x) (0x1000|((x)&0x0fff))
+#define D_XFLBIN(x) (0x2000|((x)&0x0fff))
+#define D_YFLBIN(x) (0x3000|((x)&0x0fff))
+#define D_XBIN(x) (0x4000|((x)&0x0fff))
+#define D_YBIN(x) (0x5000|((x)&0x0fff))
+#define D_EXPDUR(x) (0x6000|((x)&0x0fff))
+#define D_RESERVE(x) (0x7000|((x)&0x0fff))
+
+/* Define extended parameter fields for querying camera */
+#define EPARAM_ECHO (0x00)
+#define EPARAM_CCDID (0x01)
+#define EPARAM_FIRM (0x02)
+#define EPARAM_SNHIGH (0x03)
+#define EPARAM_SNLOW (0x04)
+#define EPARAM_SIGGAIN (0x05)
+#define EPARAM_DEVICE (0x06)
+
+/* I/O Bit definitions */
+#define FLICCD_IO_P0 (0x01)
+#define FLICCD_IO_P1 (0x02)
+#define FLICCD_IO_P2 (0x04)
+#define FLICCD_IO_P3 (0x08)
+
+long fli_camera_parport_open(flidev_t dev);
+long fli_camera_parport_get_array_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y);
+long fli_camera_parport_get_visible_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y);
+long fli_camera_parport_set_exposure_time(flidev_t dev, long exptime);
+long fli_camera_parport_set_image_area(flidev_t dev, long ul_x, long ul_y,
+ long lr_x, long lr_y);
+long fli_camera_parport_set_hbin(flidev_t dev, long hbin);
+long fli_camera_parport_set_vbin(flidev_t dev, long vbin);
+long fli_camera_parport_get_exposure_status(flidev_t dev, long *timeleft);
+long fli_camera_parport_set_temperature(flidev_t dev, double temperature);
+long fli_camera_parport_get_temperature(flidev_t dev, double *temperature);
+long fli_camera_parport_grab_row(flidev_t dev, void *buf, size_t width);
+long fli_camera_parport_expose_frame(flidev_t dev);
+long fli_camera_parport_flush_rows(flidev_t dev, long rows, long repeat);
+long fli_camera_parport_set_bit_depth(flidev_t dev, flibitdepth_t bitdepth);
+long fli_camera_parport_read_ioport(flidev_t dev, long *ioportset);
+long fli_camera_parport_write_ioport(flidev_t dev, long ioportset);
+long fli_camera_parport_configure_ioport(flidev_t dev, long ioportset);
+long fli_camera_parport_control_shutter(flidev_t dev, long shutter);
+
+#endif /* _LIBFLI_CAMERA_PARPORT_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-camera-usb.c b/kstars/kstars/indi/fli/libfli-camera-usb.c
new file mode 100644
index 00000000..6bc88f1f
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-camera-usb.c
@@ -0,0 +1,776 @@
+/*
+
+ 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
+
+*/
+
+#ifdef WIN32
+#include <winsock.h>
+#else
+#include <sys/param.h>
+#include <netinet/in.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <math.h>
+
+#include "libfli-libfli.h"
+#include "libfli-debug.h"
+#include "libfli-mem.h"
+#include "libfli-camera.h"
+#include "libfli-camera-usb.h"
+
+double dconvert(void *buf)
+{
+ unsigned char *fnum = (unsigned char *) buf;
+ double sign, exponent, mantissa, result;
+
+ sign = (double) ((fnum[3] & 0x80)?(-1):(1));
+ exponent = (double) ((fnum[3] & 0x7f) << 1 | ((fnum[2] & 0x80)?1:0));
+
+ mantissa = 1.0 +
+ ((double) ((fnum[2] & 0x7f) << 16 | fnum[1] << 8 | fnum[0]) /
+ pow(2, 23));
+
+ result = sign * (double) pow(2, (exponent - 127.0)) * mantissa;
+
+ return result;
+}
+
+long fli_camera_usb_open(flidev_t dev)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[32];
+
+ cam = DEVICE->device_data;
+
+ if ((cam->gbuf = xmalloc(USB_READ_SIZ_MAX)) == NULL)
+ return -ENOMEM;
+
+ buf[0] = htons(FLI_USBCAM_HARDWAREREV);
+ rlen = 2; wlen = 2;
+ IO(dev, buf, &wlen, &rlen);
+ DEVICE->devinfo.hwrev = ntohs(buf[0]);
+
+ buf[0] = htons(FLI_USBCAM_DEVICEID);
+ rlen = 2; wlen = 2;
+ IO(dev, buf, &wlen, &rlen);
+ DEVICE->devinfo.devid = ntohs(buf[0]);
+
+ buf[0] = htons(FLI_USBCAM_SERIALNUM);
+ rlen = 2; wlen = 2;
+ IO(dev, buf, &wlen, &rlen);
+ DEVICE->devinfo.serno = ntohs(buf[0]);
+
+ debug(FLIDEBUG_INFO, "DeviceID %d", DEVICE->devinfo.devid);
+ debug(FLIDEBUG_INFO, "SerialNum %d", DEVICE->devinfo.serno);
+ debug(FLIDEBUG_INFO, "HWRev %d", DEVICE->devinfo.hwrev);
+ debug(FLIDEBUG_INFO, "FWRev %d", DEVICE->devinfo.fwrev);
+
+ if (DEVICE->devinfo.fwrev < 0x0201)
+ {
+ int id;
+
+ for (id = 0; knowndev[id].index != 0; id++)
+ if (knowndev[id].index == DEVICE->devinfo.devid)
+ break;
+
+ if (knowndev[id].index == 0)
+ return -ENODEV;
+
+ cam->ccd.pixelwidth = knowndev[id].pixelwidth;
+ cam->ccd.pixelheight = knowndev[id].pixelheight;
+
+ wlen = sizeof(unsigned short) * 7;
+ rlen = 0;
+ buf[0] = htons(FLI_USBCAM_DEVINIT);
+ buf[1] = htons((unsigned short)knowndev[id].array_area.lr.x);
+ buf[2] = htons((unsigned short)knowndev[id].array_area.lr.y);
+ buf[3] = htons((unsigned short)(knowndev[id].visible_area.lr.x -
+ knowndev[id].visible_area.ul.x));
+ buf[4] = htons((unsigned short)(knowndev[id].visible_area.lr.y -
+ knowndev[id].visible_area.ul.y));
+ buf[5] = htons((unsigned short)knowndev[id].visible_area.ul.x);
+ buf[6] = htons((unsigned short)knowndev[id].visible_area.ul.y);
+ IO(dev, buf, &wlen, &rlen);
+ if ((DEVICE->devinfo.model =
+ (char *)xmalloc(strlen(knowndev[id].model) + 1)) == NULL)
+ return -ENOMEM;
+ strcpy(DEVICE->devinfo.model, knowndev[id].model);
+
+ switch(DEVICE->devinfo.fwrev & 0xff00)
+ {
+ case 0x0100:
+ cam->tempslope = (70.0 / 215.75);
+ cam->tempintercept = (-52.5681);
+ break;
+
+ case 0x0200:
+ cam->tempslope = (100.0 / 201.1);
+ cam->tempintercept = (-61.613);
+ break;
+
+ default:
+ cam->tempslope = 1e-12;
+ cam->tempintercept = 0;
+ }
+ }
+ else if (DEVICE->devinfo.fwrev >= 0x0201) /* Here, all the parameters are stored on the camera */
+ {
+ rlen = 64; wlen = 2;
+ buf[0] = htons(FLI_USBCAM_READPARAMBLOCK);
+ IO(dev, buf, &wlen, &rlen);
+
+ cam->ccd.pixelwidth = dconvert((char *) ((void *)buf) + 31);
+ cam->ccd.pixelheight = dconvert((char*) ((void *)buf) + 35);
+ cam->tempslope = dconvert((char *) ((void *)buf) + 23);
+ cam->tempintercept = dconvert((char *) ((void *)buf) + 27);
+ }
+
+ rlen = 32; wlen = 2;
+ buf[0] = htons(FLI_USBCAM_DEVICENAME);
+ IO(dev, buf, &wlen, &rlen);
+
+ if ((DEVICE->devinfo.devnam = (char *)xmalloc(rlen + 1)) == NULL)
+ return -ENOMEM;
+ memcpy(DEVICE->devinfo.devnam, buf, rlen);
+ DEVICE->devinfo.devnam[rlen] = '\0';
+
+ if(DEVICE->devinfo.model == NULL)
+ {
+ DEVICE->devinfo.model = xstrdup(DEVICE->devinfo.devnam);
+ }
+
+ rlen = 4; wlen = 2;
+ buf[0] = htons(FLI_USBCAM_ARRAYSIZE);
+ IO(dev, buf, &wlen, &rlen);
+ cam->ccd.array_area.ul.x = 0;
+ cam->ccd.array_area.ul.y = 0;
+ cam->ccd.array_area.lr.x = ntohs(buf[0]);
+ cam->ccd.array_area.lr.y = ntohs(buf[1]);
+
+ rlen = 4; wlen = 2;
+ buf[0] = htons(FLI_USBCAM_IMAGEOFFSET);
+ IO(dev, buf, &wlen, &rlen);
+ cam->ccd.visible_area.ul.x = ntohs(buf[0]);
+ cam->ccd.visible_area.ul.y = ntohs(buf[1]);
+
+ rlen = 4; wlen = 2;
+ buf[0] = htons(FLI_USBCAM_IMAGESIZE);
+ IO(dev, buf, &wlen, &rlen);
+ cam->ccd.visible_area.lr.x = cam->ccd.visible_area.ul.x + ntohs(buf[0]);
+ cam->ccd.visible_area.lr.y = cam->ccd.visible_area.ul.y + ntohs(buf[1]);
+
+ debug(FLIDEBUG_INFO, " Name: %s", DEVICE->devinfo.devnam);
+ debug(FLIDEBUG_INFO, " Array: (%4d,%4d),(%4d,%4d)",
+ cam->ccd.array_area.ul.x,
+ cam->ccd.array_area.ul.y,
+ cam->ccd.array_area.lr.x,
+ cam->ccd.array_area.lr.y);
+ debug(FLIDEBUG_INFO, " Visible: (%4d,%4d),(%4d,%4d)",
+ cam->ccd.visible_area.ul.x,
+ cam->ccd.visible_area.ul.y,
+ cam->ccd.visible_area.lr.x,
+ cam->ccd.visible_area.lr.y);
+
+ debug(FLIDEBUG_INFO, " Pix Size: (%g, %g)", cam->ccd.pixelwidth, cam->ccd.pixelheight);
+ debug(FLIDEBUG_INFO, " Temp.: T = AD x %g + %g", cam->tempslope, cam->tempintercept);
+
+ /* Initialize all varaibles to something */
+
+ cam->vflushbin = 4;
+ cam->hflushbin = 4;
+ cam->vbin = 1;
+ cam->hbin = 1;
+ cam->image_area.ul.x = cam->ccd.visible_area.ul.x;
+ cam->image_area.ul.y = cam->ccd.visible_area.ul.y;
+ cam->image_area.lr.x = cam->ccd.visible_area.lr.x;
+ cam->image_area.lr.y = cam->ccd.visible_area.lr.y;
+ cam->exposure = 100;
+ cam->frametype = FLI_FRAME_TYPE_NORMAL;
+ cam->flushes = 0;
+ cam->bitdepth = FLI_MODE_16BIT;
+ cam->exttrigger = 0;
+ cam->exttriggerpol = 0;
+
+ cam->grabrowwidth =
+ (cam->image_area.lr.x - cam->image_area.ul.x) / cam->hbin;
+ cam->grabrowcount = 1;
+ cam->grabrowcounttot = cam->grabrowcount;
+ cam->grabrowindex = 0;
+ cam->grabrowbatchsize = 1;
+ cam->grabrowbufferindex = cam->grabrowcount;
+ cam->flushcountbeforefirstrow = 0;
+ cam->flushcountafterlastrow = 0;
+
+ return 0;
+}
+
+long fli_camera_usb_get_array_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ cam = DEVICE->device_data;
+
+ rlen = 4; wlen = 2;
+ buf[0] = htons(FLI_USBCAM_ARRAYSIZE);
+ IO(dev, buf, &wlen, &rlen);
+ cam->ccd.array_area.ul.x = 0;
+ cam->ccd.array_area.ul.y = 0;
+ cam->ccd.array_area.lr.x = ntohs(buf[0]);
+ cam->ccd.array_area.lr.y = ntohs(buf[1]);
+
+ *ul_x = cam->ccd.array_area.ul.x;
+ *ul_y = cam->ccd.array_area.ul.y;
+ *lr_x = cam->ccd.array_area.lr.x;
+ *lr_y = cam->ccd.array_area.lr.y;
+
+ return 0;
+}
+
+long fli_camera_usb_get_visible_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ cam = DEVICE->device_data;
+
+ rlen = 4; wlen = 2;
+ buf[0] = htons(FLI_USBCAM_IMAGEOFFSET);
+ IO(dev, buf, &wlen, &rlen);
+ cam->ccd.visible_area.ul.x = ntohs(buf[0]);
+ cam->ccd.visible_area.ul.y = ntohs(buf[1]);
+
+ rlen = 4; wlen = 2;
+ buf[0] = htons(FLI_USBCAM_IMAGESIZE);
+ IO(dev, buf, &wlen, &rlen);
+ cam->ccd.visible_area.lr.x = cam->ccd.visible_area.ul.x + ntohs(buf[0]);
+ cam->ccd.visible_area.lr.y = cam->ccd.visible_area.ul.y + ntohs(buf[1]);
+
+ *ul_x = cam->ccd.visible_area.ul.x;
+ *ul_y = cam->ccd.visible_area.ul.y;
+ *lr_x = cam->ccd.visible_area.lr.x;
+ *lr_y = cam->ccd.visible_area.lr.y;
+
+ return 0;
+}
+
+long fli_camera_usb_set_exposure_time(flidev_t dev, long exptime)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ if (exptime < 0)
+ return -EINVAL;
+
+ cam = DEVICE->device_data;
+
+ rlen = 0; wlen = 8;
+ buf[0] = htons(FLI_USBCAM_SETEXPOSURE);
+ ((unsigned long *)((void *) buf))[1] = htonl(exptime);
+ IO(dev, buf, &wlen, &rlen);
+
+ cam->exposure = exptime;
+
+ return 0;
+}
+
+long fli_camera_usb_set_image_area(flidev_t dev, long ul_x, long ul_y,
+ long lr_x, long lr_y)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ cam = DEVICE->device_data;
+
+ if( (DEVICE->devinfo.fwrev < 0x0300) &&
+ ((DEVICE->devinfo.hwrev & 0xff00) == 0x0100) )
+ {
+ if( (lr_x > (cam->ccd.visible_area.lr.x * cam->hbin)) ||
+ (lr_y > (cam->ccd.visible_area.lr.y * cam->vbin)) )
+ {
+ debug(FLIDEBUG_WARN,
+ "FLISetVisibleArea(), area out of bounds: (%4d,%4d),(%4d,%4d)",
+ ul_x, ul_y, lr_x, lr_y);
+ }
+ }
+
+ if( (ul_x < cam->ccd.visible_area.ul.x) ||
+ (ul_y < cam->ccd.visible_area.ul.y) )
+ {
+ debug(FLIDEBUG_FAIL,
+ "FLISetVisibleArea(), area out of bounds: (%4d,%4d),(%4d,%4d)",
+ ul_x, ul_y, lr_x, lr_y);
+ return -EINVAL;
+ }
+
+ rlen = 0; wlen = 6;
+ buf[0] = htons(FLI_USBCAM_SETFRAMEOFFSET);
+ buf[1] = htons((unsigned short) cam->image_area.ul.x);
+ buf[2] = htons((unsigned short) cam->image_area.ul.y);
+ IO(dev, buf, &wlen, &rlen);
+
+ cam->image_area.ul.x = ul_x;
+ cam->image_area.ul.y = ul_y;
+ cam->image_area.lr.x = lr_x;
+ cam->image_area.lr.y = lr_y;
+ cam->grabrowwidth =
+ (cam->image_area.lr.x - cam->image_area.ul.x) / cam->hbin;
+
+ return 0;
+}
+
+long fli_camera_usb_set_hbin(flidev_t dev, long hbin)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ cam = DEVICE->device_data;
+
+ if ((hbin < 1) || (hbin > 16))
+ return -EINVAL;
+
+ rlen = 0; wlen = 6;
+ buf[0] = htons(FLI_USBCAM_SETBINFACTORS);
+ buf[1] = htons((unsigned short) hbin);
+ buf[2] = htons((unsigned short) cam->vbin);
+ IO(dev, buf, &wlen, &rlen);
+
+ cam->hbin = hbin;
+ cam->grabrowwidth =
+ (cam->image_area.lr.x - cam->image_area.ul.x) / cam->hbin;
+
+ return 0;
+}
+
+long fli_camera_usb_set_vbin(flidev_t dev, long vbin)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ cam = DEVICE->device_data;
+
+ if ((vbin < 1) || (vbin > 16))
+ return -EINVAL;
+
+ rlen = 0; wlen = 6;
+ buf[0] = htons(FLI_USBCAM_SETBINFACTORS);
+ buf[1] = htons((unsigned short) cam->hbin);
+ buf[2] = htons((unsigned short) vbin);
+ IO(dev, buf, &wlen, &rlen);
+
+ cam->vbin = vbin;
+
+ return 0;
+}
+
+long fli_camera_usb_get_exposure_status(flidev_t dev, long *timeleft)
+{
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ rlen = 4; wlen = 2;
+ buf[0] = htons(FLI_USBCAM_EXPOSURESTATUS);
+ IO(dev, buf, &wlen, &rlen);
+ *timeleft = ntohl(((unsigned long *)((void *) buf))[0]);
+
+ return 0;
+}
+
+long fli_camera_usb_set_temperature(flidev_t dev, double temperature)
+{
+ flicamdata_t *cam;
+ unsigned short ad;
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ cam = DEVICE->device_data;
+
+ if(DEVICE->devinfo.fwrev < 0x0200)
+ {
+ return 0;
+ }
+
+ if(cam->tempslope == 0.0)
+ {
+ ad = 255;
+ }
+ else
+ {
+ ad = (unsigned short) ((temperature - cam->tempintercept) / cam->tempslope);
+ }
+
+ debug(FLIDEBUG_INFO, "Temperature slope, intercept, AD val, %f %f %f %d", temperature, cam->tempslope, cam->tempintercept, ad);
+
+ rlen = 0; wlen = 4;
+ buf[0] = htons(FLI_USBCAM_TEMPERATURE);
+ buf[1] = htons(ad);
+ IO(dev, buf, &wlen, &rlen);
+
+ return 0;
+}
+
+long fli_camera_usb_get_temperature(flidev_t dev, double *temperature)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[16];
+
+ cam = DEVICE->device_data;
+
+ rlen = 2; wlen = 2;
+ buf[0] = htons(FLI_USBCAM_TEMPERATURE);
+ IO(dev, buf, &wlen, &rlen);
+ *temperature = cam->tempslope * (double)((ntohs(buf[0]) & 0x00ff)) +
+ cam->tempintercept;
+
+ return 0;
+}
+
+long fli_camera_usb_grab_row(flidev_t dev, void *buff, size_t width)
+{
+ flicamdata_t *cam;
+ long x;
+ long r;
+
+ cam = DEVICE->device_data;
+
+ if(width > (size_t) (cam->image_area.lr.x - cam->image_area.ul.x))
+ {
+ debug(FLIDEBUG_FAIL, "FLIGrabRow(), requested row too wide.");
+ debug(FLIDEBUG_FAIL, " Requested width: %d", width);
+ debug(FLIDEBUG_FAIL, " FLISetImageArea() width: %d",
+ cam->image_area.lr.x - cam->image_area.ul.x);
+ return -EINVAL;
+ }
+
+ if (cam->flushcountbeforefirstrow > 0)
+ {
+ if ((r = fli_camera_usb_flush_rows(dev, cam->flushcountbeforefirstrow, 1)))
+ return r;
+
+ cam->flushcountbeforefirstrow = 0;
+ }
+
+ if (cam->grabrowbufferindex >= cam->grabrowbatchsize)
+ {
+ /* We don't have the row in memory */
+ long rlen, wlen;
+
+ /* Do we have less than GrabRowBatchSize rows to grab? */
+ if (cam->grabrowbatchsize > (cam->grabrowcounttot - cam->grabrowindex))
+ {
+ cam->grabrowbatchsize = cam->grabrowcounttot - cam->grabrowindex;
+ }
+
+ rlen = cam->grabrowwidth * 2 * cam->grabrowbatchsize;
+ wlen = 6;
+ cam->gbuf[0] = htons(FLI_USBCAM_SENDROW);
+ cam->gbuf[1] = htons((unsigned short) cam->grabrowwidth);
+ cam->gbuf[2] = htons((unsigned short) cam->grabrowbatchsize);
+ IO(dev, cam->gbuf, &wlen, &rlen);
+
+ for (x = 0; x < (cam->grabrowwidth * cam->grabrowbatchsize); x++)
+ {
+ if ((DEVICE->devinfo.hwrev & 0xff00) == 0x0100)
+ {
+ cam->gbuf[x] = ntohs(cam->gbuf[x]) + 32768;
+ }
+ else
+ {
+ cam->gbuf[x] = ntohs(cam->gbuf[x]);
+ }
+ }
+ cam->grabrowbufferindex = 0;
+ }
+
+ for (x = 0; x < (long)width; x++)
+ {
+ ((unsigned short *)buff)[x] =
+ cam->gbuf[x + (cam->grabrowbufferindex * cam->grabrowwidth)];
+ }
+
+ cam->grabrowbufferindex++;
+ cam->grabrowindex++;
+
+ if (cam->grabrowcount > 0)
+ {
+ cam->grabrowcount--;
+ if (cam->grabrowcount == 0)
+ {
+ if ((r = fli_camera_usb_flush_rows(dev, cam->flushcountafterlastrow, 1)))
+ return r;
+
+ cam->flushcountafterlastrow = 0;
+ cam->grabrowbatchsize = 1;
+ }
+ }
+
+ return 0;
+}
+
+long fli_camera_usb_expose_frame(flidev_t dev)
+{
+ flicamdata_t *cam;
+ short flags = 0;
+ long rlen, wlen;
+ unsigned short buf[16];
+
+ cam = DEVICE->device_data;
+
+ rlen = 0; wlen = 6;
+ buf[0] = htons(FLI_USBCAM_SETFRAMEOFFSET);
+ buf[1] = htons((unsigned short) cam->image_area.ul.x);
+ buf[2] = htons((unsigned short) cam->image_area.ul.y);
+ IO(dev, buf, &wlen, &rlen);
+
+ rlen = 0; wlen = 6;
+ buf[0] = htons(FLI_USBCAM_SETBINFACTORS);
+ buf[1] = htons((unsigned short) cam->hbin);
+ buf[2] = htons((unsigned short) cam->vbin);
+ IO(dev, buf, &wlen, &rlen);
+
+ rlen = 0; wlen = 6;
+ buf[0] = htons(FLI_USBCAM_SETFLUSHBINFACTORS);
+ buf[1] = htons((unsigned short) cam->hflushbin);
+ buf[2] = htons((unsigned short) cam->vflushbin);
+ IO(dev, buf, &wlen, &rlen);
+
+ rlen = 0; wlen = 8;
+ buf[0] = htons(FLI_USBCAM_SETEXPOSURE);
+ ((unsigned long *)((void *) buf))[1] = htonl(cam->exposure);
+ IO(dev, buf, &wlen, &rlen);
+
+ /* What flags do we need to send... */
+ /* Dark Frame */
+ flags |= (cam->frametype == FLI_FRAME_TYPE_DARK) ? 0x01 : 0x00;
+ /* External trigger */
+ flags |= (cam->exttrigger != 0) ? 0x04 : 0x00;
+ flags |= (cam->exttriggerpol != 0) ? 0x08 : 0x00;
+
+ debug(FLIDEBUG_INFO, "Exposure flags: %04x", flags);
+
+ debug(FLIDEBUG_INFO, "Flushing %d times.\n", cam->flushes);
+ if (cam->flushes > 0)
+ {
+ long r;
+
+ if ((r = fli_camera_usb_flush_rows(dev,
+ cam->ccd.array_area.lr.y - cam->ccd.array_area.ul.y,
+ cam->flushes)))
+ return r;
+ }
+
+ rlen = 0; wlen = 4;
+ buf[0] = htons(FLI_USBCAM_STARTEXPOSURE);
+ buf[1] = htons((unsigned short) flags);
+ IO(dev, buf, &wlen, &rlen);
+
+ cam->grabrowcount = cam->image_area.lr.y - cam->image_area.ul.y;
+ cam->grabrowcounttot = cam->grabrowcount;
+ cam->grabrowwidth = cam->image_area.lr.x - cam->image_area.ul.x;
+ cam->grabrowindex = 0;
+ cam->grabrowbatchsize = USB_READ_SIZ_MAX / (cam->grabrowwidth * 2);
+
+ /* Lets put some bounds on this... */
+ if (cam->grabrowbatchsize > cam->grabrowcounttot)
+ cam->grabrowbatchsize = cam->grabrowcounttot;
+
+ if (cam->grabrowbatchsize > 64)
+ cam->grabrowbatchsize = 64;
+
+ /* We need to get a whole new buffer by default */
+ cam->grabrowbufferindex = cam->grabrowbatchsize;
+
+ cam->flushcountbeforefirstrow = cam->image_area.ul.y;
+ cam->flushcountafterlastrow =
+ (cam->ccd.array_area.lr.y - cam->ccd.array_area.ul.y) -
+ ((cam->image_area.lr.y - cam->image_area.ul.y) * cam->vbin) -
+ cam->image_area.ul.y;
+
+ if (cam->flushcountbeforefirstrow < 0)
+ cam->flushcountbeforefirstrow = 0;
+
+ if (cam->flushcountafterlastrow < 0)
+ cam->flushcountafterlastrow = 0;
+
+ return 0;
+}
+
+long fli_camera_usb_flush_rows(flidev_t dev, long rows, long repeat)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[16];
+
+ cam = DEVICE->device_data;
+
+ if (rows < 0)
+ return -EINVAL;
+
+ if (rows == 0)
+ return 0;
+
+ rlen = 0; wlen = 6;
+ buf[0] = htons(FLI_USBCAM_SETFLUSHBINFACTORS);
+ buf[1] = htons((unsigned short) cam->hflushbin);
+ buf[2] = htons((unsigned short) cam->vflushbin);
+ IO(dev, buf, &wlen, &rlen);
+
+ while (repeat > 0)
+ {
+ rlen = 0; wlen = 4;
+ buf[0] = htons(FLI_USBCAM_FLUSHROWS);
+ buf[1] = htons((unsigned short) rows);
+ IO(dev, buf, &wlen, &rlen);
+ repeat--;
+ }
+
+ return 0;
+}
+
+long fli_camera_usb_set_bit_depth(flidev_t dev, flibitdepth_t bitdepth)
+{
+ dev=dev; bitdepth=bitdepth;
+ return -EINVAL;
+}
+
+long fli_camera_usb_read_ioport(flidev_t dev, long *ioportset)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ cam = DEVICE->device_data;
+
+ rlen = 1; wlen = 2;
+ buf[0] = htons(FLI_USBCAM_READIO);
+ IO(dev, buf, &wlen, &rlen);
+ *ioportset = ((unsigned char *)(void *)buf)[0];
+
+ return 0;
+}
+
+long fli_camera_usb_write_ioport(flidev_t dev, long ioportset)
+{
+ flicamdata_t *cam;
+
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ cam = DEVICE->device_data;
+
+ rlen = 0; wlen = 3;
+ buf[0] = htons(FLI_USBCAM_WRITEIO);
+ ((unsigned char *)(void *)buf)[2] = (char)ioportset;
+ IO(dev, buf, &wlen, &rlen);
+
+ return 0;
+}
+
+long fli_camera_usb_configure_ioport(flidev_t dev, long ioportset)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ cam = DEVICE->device_data;
+
+ rlen = 0; wlen = 3;
+ buf[0] = htons(FLI_USBCAM_WRITEDIR);
+ ((unsigned char *)(void *)buf)[2] = (char)ioportset;
+ IO(dev, buf, &wlen, &rlen);
+
+ return 0;
+}
+
+long fli_camera_usb_control_shutter(flidev_t dev, long shutter)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ cam = DEVICE->device_data;
+
+ rlen = 0; wlen = 3;
+ buf[0] = htons(FLI_USBCAM_SHUTTER);
+ ((unsigned char *)(void *)buf)[2] = (char)shutter;
+ IO(dev, buf, &wlen, &rlen);
+
+ return 0;
+}
+
+long fli_camera_usb_control_bgflush(flidev_t dev, long bgflush)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf[8];
+
+ cam = DEVICE->device_data;
+
+ if(DEVICE->devinfo.fwrev < 0x0300)
+ {
+ debug(FLIDEBUG_WARN, "Background flush commanded on early firmware.");
+ return -EFAULT;
+ }
+
+ if( (bgflush != FLI_BGFLUSH_STOP) &&
+ (bgflush != FLI_BGFLUSH_START) )
+ return -EINVAL;
+
+ rlen = 0; wlen = 4;
+ buf[0] = htons(FLI_USBCAM_BGFLUSH);
+ buf[1] = htons((unsigned short) bgflush);
+ IO(dev, buf, &wlen, &rlen);
+
+ return 0;
+}
diff --git a/kstars/kstars/indi/fli/libfli-camera-usb.h b/kstars/kstars/indi/fli/libfli-camera-usb.h
new file mode 100644
index 00000000..f2c79037
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-camera-usb.h
@@ -0,0 +1,98 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_CAMERA_USB_H_
+#define _LIBFLI_CAMERA_USB_H_
+
+#define FLI_USBCAM_DEVICENAME 0x01
+#define FLI_USBCAM_DEVICEMFG 0x02
+#define FLI_USBCAM_VERSION 0x03
+#define FLI_USBCAM_DEVICEID 0x04
+#define FLI_USBCAM_SERIALNUM 0x05
+#define FLI_USBCAM_HARDWAREREV 0x06
+#define FLI_USBCAM_DEVINIT 0x07
+#define FLI_USBCAM_READPARAMBLOCK 0x08
+
+#define FLI_USBCAM_ARRAYSIZE 0x100
+#define FLI_USBCAM_IMAGEOFFSET 0x102
+#define FLI_USBCAM_IMAGESIZE 0x103
+#define FLI_USBCAM_TEMPERATURE 0x104
+#define FLI_USBCAM_SETFRAMEOFFSET 0x105
+#define FLI_USBCAM_SETBINFACTORS 0x106
+#define FLI_USBCAM_SETFLUSHBINFACTORS 0x107
+#define FLI_USBCAM_SETEXPOSURE 0x108
+#define FLI_USBCAM_STARTEXPOSURE 0x109
+#define FLI_USBCAM_ABORTEXPOSURE 0x10a
+#define FLI_USBCAM_EXPOSURESTATUS 0x10b
+#define FLI_USBCAM_FLUSHROWS 0x10c
+#define FLI_USBCAM_SENDROW 0x10d
+#define FLI_USBCAM_SHUTTER 0x10f
+#define FLI_USBCAM_WRITEIO 0x110
+#define FLI_USBCAM_READIO 0x111
+#define FLI_USBCAM_WRITEDIR 0x112
+#define FLI_USBCAM_BGFLUSH 0x114
+
+long fli_camera_usb_open(flidev_t dev);
+long fli_camera_usb_get_array_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y);
+long fli_camera_usb_get_visible_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y);
+long fli_camera_usb_set_exposure_time(flidev_t dev, long exptime);
+long fli_camera_usb_set_image_area(flidev_t dev, long ul_x, long ul_y,
+ long lr_x, long lr_y);
+long fli_camera_usb_set_hbin(flidev_t dev, long hbin);
+long fli_camera_usb_set_vbin(flidev_t dev, long vbin);
+long fli_camera_usb_get_exposure_status(flidev_t dev, long *timeleft);
+long fli_camera_usb_set_temperature(flidev_t dev, double temperature);
+long fli_camera_usb_get_temperature(flidev_t dev, double *temperature);
+long fli_camera_usb_grab_row(flidev_t dev, void *buff, size_t width);
+long fli_camera_usb_expose_frame(flidev_t dev);
+long fli_camera_usb_flush_rows(flidev_t dev, long rows, long repeat);
+long fli_camera_usb_set_bit_depth(flidev_t dev, flibitdepth_t bitdepth);
+long fli_camera_usb_read_ioport(flidev_t dev, long *ioportset);
+long fli_camera_usb_write_ioport(flidev_t dev, long ioportset);
+long fli_camera_usb_configure_ioport(flidev_t dev, long ioportset);
+long fli_camera_usb_control_shutter(flidev_t dev, long shutter);
+long fli_camera_usb_control_bgflush(flidev_t dev, long bgflush);
+
+#endif /* _LIBFLI_CAMERA_USB_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-camera.c b/kstars/kstars/indi/fli/libfli-camera.c
new file mode 100644
index 00000000..369b0038
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-camera.c
@@ -0,0 +1,790 @@
+/*
+
+ 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 <stdio.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include "libfli-libfli.h"
+#include "libfli-debug.h"
+#include "libfli-mem.h"
+#include "libfli-camera.h"
+#include "libfli-camera-parport.h"
+#include "libfli-camera-usb.h"
+
+const fliccdinfo_t knowndev[] = {
+ /* id model array_area visible_area */
+ {1, "KAF-0260C0-2", {{0, 0}, {534, 520}}, {{12, 4}, {524, 516}}, 1.0, 20.0, 20.0},
+ {2, "KAF-0400C0-2", {{0, 0}, {796, 520}}, {{14, 4}, {782, 516}}, 1.0, 20.0, 20.0},
+ {3, "KAF-1000C0-2", {{0, 0}, {1042, 1032}}, {{8, 4}, {1032, 1028}}, 1.0, 24.0, 24.0},
+ {4, "KAF-1300C0-2", {{0, 0}, {1304, 1028}}, {{4, 2}, {1284, 1026}}, 1.0, 20.0, 20.0},
+ {5, "KAF-1400C0-2", {{0, 0}, {1348, 1037}}, {{14,14}, {782, 526}}, 1.0, 20.0, 20.0},
+ {6, "KAF-1600C0-2", {{0, 0}, {1564, 1032}}, {{14, 4}, {1550, 1028}}, 1.0, 20.0, 20.0},
+ {7, "KAF-4200C0-2", {{0, 0}, {2060, 2048}}, {{25, 2}, {2057, 2046}}, 1.0, 20.0, 20.0},
+ {8, "SITe-502S", {{0, 0}, {527, 512}}, {{15, 0}, {527, 512}}, 1.0, 20.0, 20.0},
+ {9, "TK-1024", {{0, 0}, {1124, 1024}}, {{50, 0}, {1074, 1024}}, 1.0, 24.0, 24.0},
+ {10, "TK-512", {{0, 0}, {563, 512}}, {{51, 0}, {563, 512}}, 1.0, 24.0, 24.0},
+ {11, "SI-003A", {{0, 0}, {1056, 1024}}, {{16, 0}, {1040, 1024}}, 1.0, 24.0, 24.0},
+ {12, "KAF-6300", {{0, 0}, {3100, 2056}}, {{16, 4}, {3088, 2052}}, 1.0, 9.0, 9.0},
+ {13, "KAF-3200", {{0, 0}, {2267, 1510}}, {{46,34}, {2230, 1506}}, 1.0, 6.8, 6.8},
+ {14, "SI424A", {{0, 0}, {2088, 2049}}, {{20, 0}, {2068, 2049}}, 1.0, 6.8, 6.8},
+ {15, "CCD47-10", {{0, 0}, {1072, 1027}}, {{8, 0}, {1064, 1027}}, 0.0, 0.0, 0.0},
+ {16, "CCD77", {{0, 0}, {527, 512}}, {{15, 0}, {527, 512}}, 0.0, 0.0, 0.0},
+ {17, "CCD42-40", {{0, 0}, {2148, 2048}}, {{50, 0}, {2098, 2048}}, 1.0, 13.5, 13.5},
+ {18, "KAF-4300", {{0, 0}, {2102, 2092}}, {{8, 4}, {2092, 2088}}, 1.0, 24.0, 24.0},
+ {19, "KAF-16801", {{0, 0}, {4145, 4128}}, {{44,29}, {4124, 4109}}, 1.0, 9.0, 9.0},
+ {0, "Unknown Model", {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, 0.0, 0.0, 0.0}
+};
+
+/* Common camera routines */
+static long fli_camera_get_pixel_size(flidev_t dev,
+ double *pixel_x, double *pixel_y);
+#define fli_camera_parport_get_pixel_size fli_camera_get_pixel_size
+#define fli_camera_usb_get_pixel_size fli_camera_get_pixel_size
+
+static long fli_camera_set_frame_type(flidev_t dev, fliframe_t frametype);
+#define fli_camera_parport_set_frame_type fli_camera_set_frame_type
+#define fli_camera_usb_set_frame_type fli_camera_set_frame_type
+
+static long fli_camera_set_flushes(flidev_t dev, long nflushes);
+#define fli_camera_parport_set_flushes fli_camera_set_flushes
+#define fli_camera_usb_set_flushes fli_camera_set_flushes
+
+long fli_camera_open(flidev_t dev)
+{
+ int r;
+
+ CHKDEVICE(dev);
+
+ if ((DEVICE->device_data = xcalloc(1, sizeof(flicamdata_t))) == NULL)
+ return -ENOMEM;
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_open(dev);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_open(dev);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+
+ if (r)
+ {
+ xfree(DEVICE->device_data);
+ DEVICE->device_data = NULL;
+ }
+
+ return r;
+}
+
+long fli_camera_close(flidev_t dev)
+{
+ flicamdata_t *cam;
+
+ CHKDEVICE(dev);
+
+ cam = DEVICE->device_data;
+
+ if (cam->gbuf != NULL)
+ {
+ xfree(cam->gbuf);
+ cam->gbuf = NULL;
+ }
+
+ if (DEVICE->devinfo.model != NULL)
+ {
+ xfree(DEVICE->devinfo.model);
+ DEVICE->devinfo.model = NULL;
+ }
+
+ if (DEVICE->devinfo.devnam != NULL)
+ {
+ xfree(DEVICE->devinfo.devnam);
+ DEVICE->devinfo.devnam = NULL;
+ }
+
+ if (DEVICE->device_data != NULL)
+ {
+ xfree(DEVICE->device_data);
+ DEVICE->device_data = NULL;
+ }
+
+ return 0;
+}
+
+long fli_camera_command(flidev_t dev, int cmd, int argc, ...)
+{
+ long r;
+ va_list ap;
+
+ va_start(ap, argc);
+ CHKDEVICE(dev);
+
+ switch (cmd)
+ {
+ case FLI_GET_PIXEL_SIZE:
+ if (argc != 2)
+ r = -EINVAL;
+ else
+ {
+ double *pixel_x, *pixel_y;
+
+ pixel_x = va_arg(ap, double *);
+ pixel_y = va_arg(ap, double *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_get_pixel_size(dev, pixel_x, pixel_y);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_get_pixel_size(dev, pixel_x, pixel_y);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_GET_ARRAY_AREA:
+ if (argc != 4)
+ r = -EINVAL;
+ else
+ {
+ long *ul_x, *ul_y, *lr_x, *lr_y;
+
+ ul_x = va_arg(ap, long *);
+ ul_y = va_arg(ap, long *);
+ lr_x = va_arg(ap, long *);
+ lr_y = va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_get_array_area(dev, ul_x, ul_y, lr_x, lr_y);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_get_array_area(dev, ul_x, ul_y, lr_x, lr_y);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_GET_VISIBLE_AREA:
+ if (argc != 4)
+ r = -EINVAL;
+ else
+ {
+ long *ul_x, *ul_y, *lr_x, *lr_y;
+
+ ul_x = va_arg(ap, long *);
+ ul_y = va_arg(ap, long *);
+ lr_x = va_arg(ap, long *);
+ lr_y = va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_get_visible_area(dev, ul_x, ul_y, lr_x, lr_y);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_get_visible_area(dev, ul_x, ul_y, lr_x, lr_y);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_EXPOSURE_TIME:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long exptime;
+
+ exptime = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_exposure_time(dev, exptime);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_exposure_time(dev, exptime);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_IMAGE_AREA:
+ if (argc != 4)
+ r = -EINVAL;
+ else
+ {
+ long ul_x, ul_y, lr_x, lr_y;
+
+ ul_x = *va_arg(ap, long *);
+ ul_y = *va_arg(ap, long *);
+ lr_x = *va_arg(ap, long *);
+ lr_y = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_image_area(dev, ul_x, ul_y, lr_x, lr_y);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_image_area(dev, ul_x, ul_y, lr_x, lr_y);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_HBIN:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long hbin;
+
+ hbin = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_hbin(dev, hbin);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_hbin(dev, hbin);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_VBIN:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long vbin;
+
+ vbin = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_vbin(dev, vbin);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_vbin(dev, vbin);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_FRAME_TYPE:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long frametype;
+
+ frametype = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_frame_type(dev, frametype);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_frame_type(dev, frametype);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_CANCEL_EXPOSURE:
+ if (argc != 0)
+ r = -EINVAL;
+ else
+ {
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ cam->grabrowcount = 1;
+ cam->grabrowcounttot = cam->grabrowcount;
+ cam->grabrowindex = 0;
+ cam->grabrowbatchsize = 1;
+ cam->grabrowbufferindex = cam->grabrowcount;
+ cam->flushcountbeforefirstrow = 0;
+ cam->flushcountafterlastrow = 0;
+
+ r = DEVICE->fli_command(dev, FLI_CONTROL_SHUTTER, (long) FLI_SHUTTER_CLOSE);
+ }
+ break;
+
+ case FLI_GET_EXPOSURE_STATUS:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *timeleft;
+
+ timeleft = va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_get_exposure_status(dev, timeleft);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_get_exposure_status(dev, timeleft);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_TEMPERATURE:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ double temperature;
+
+ temperature = *va_arg(ap, double *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_temperature(dev, temperature);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_temperature(dev, temperature);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_GET_TEMPERATURE:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ double *temperature;
+
+ temperature = va_arg(ap, double *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_get_temperature(dev, temperature);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_get_temperature(dev, temperature);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_GRAB_ROW:
+ if (argc != 2)
+ r = -EINVAL;
+ else
+ {
+ void *buf;
+ size_t width;
+
+ buf = va_arg(ap, void *);
+ width = *va_arg(ap, size_t *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_grab_row(dev, buf, width);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_grab_row(dev, buf, width);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_EXPOSE_FRAME:
+ if (argc != 0)
+ r = -EINVAL;
+ else
+ {
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_expose_frame(dev);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_expose_frame(dev);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_FLUSH_ROWS:
+ if (argc != 2)
+ r = -EINVAL;
+ else
+ {
+ long rows, repeat;
+
+ rows = *va_arg(ap, long *);
+ repeat = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_flush_rows(dev, rows, repeat);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_flush_rows(dev, rows, repeat);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_FLUSHES:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long nflushes;
+
+ nflushes = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_flushes(dev, nflushes);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_flushes(dev, nflushes);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_BIT_DEPTH:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ flibitdepth_t bitdepth;
+
+ bitdepth = *va_arg(ap, flibitdepth_t *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_bit_depth(dev, bitdepth);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_bit_depth(dev, bitdepth);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_READ_IOPORT:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *ioportset;
+
+ ioportset = va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_read_ioport(dev, ioportset);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_read_ioport(dev, ioportset);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_WRITE_IOPORT:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long ioportset;
+
+ ioportset = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_write_ioport(dev, ioportset);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_write_ioport(dev, ioportset);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_CONFIGURE_IOPORT:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long ioportset;
+
+ ioportset = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_configure_ioport(dev, ioportset);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_configure_ioport(dev, ioportset);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_CONTROL_SHUTTER:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long shutter;
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ shutter = *va_arg(ap, long *);
+
+ if( (shutter == FLI_SHUTTER_EXTERNAL_TRIGGER_LOW) ||
+ (shutter == FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH) )
+ {
+ debug(FLIDEBUG_INFO, "External trigger.\n");
+ cam->exttrigger = 1;
+ cam->exttriggerpol = (shutter == FLI_SHUTTER_EXTERNAL_TRIGGER_LOW)?0:1;
+ r = 0;
+ }
+ else
+ {
+ cam->exttrigger = 0;
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_control_shutter(dev, shutter);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_control_shutter(dev, shutter);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ }
+ break;
+
+ case FLI_CONTROL_BGFLUSH:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long bgflush;
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ bgflush = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = -EFAULT;
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_control_bgflush(dev, bgflush);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+
+ va_end(ap);
+
+ return r;
+}
+
+static long fli_camera_get_pixel_size(flidev_t dev,
+ double *pixel_x, double *pixel_y)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+ *pixel_x = (double)cam->ccd.pixelwidth;
+ *pixel_y = (double)cam->ccd.pixelheight;
+
+ return 0;
+}
+
+static long fli_camera_set_frame_type(flidev_t dev, fliframe_t frametype)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if ((frametype < FLI_FRAME_TYPE_NORMAL) || (frametype > FLI_FRAME_TYPE_DARK))
+ return -EINVAL;
+
+ cam->frametype = frametype;
+
+ return 0;
+}
+
+static long fli_camera_set_flushes(flidev_t dev, long nflushes)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if((nflushes < 0) || (nflushes > 5))
+ return -EINVAL;
+
+ cam->flushes = nflushes;
+
+ return 0;
+}
diff --git a/kstars/kstars/indi/fli/libfli-camera.h b/kstars/kstars/indi/fli/libfli-camera.h
new file mode 100644
index 00000000..2d4f2b99
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-camera.h
@@ -0,0 +1,111 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_CAMERA_H_
+#define _LIBFLI_CAMERA_H_
+
+typedef struct {
+ int x; /* X coordinate */
+ int y; /* Y coordinate */
+} point_t;
+
+typedef struct {
+ point_t ul; /* Upper-left */
+ point_t lr; /* Lower-right */
+} area_t;
+
+/* CCD Parameter list */
+typedef struct
+{
+ short index;
+ const char *model;
+ area_t array_area;
+ area_t visible_area;
+ double fillfactor;
+ double pixelwidth;
+ double pixelheight;
+} fliccdinfo_t;
+
+typedef struct {
+ long readto;
+ long writeto;
+ long dirto;
+ fliccdinfo_t ccd;
+
+ /* Acquisistion parameters */
+ area_t image_area;
+ long vbin;
+ long hbin;
+ long vflushbin;
+ long hflushbin;
+ long exposure;
+ long expdur;
+ long expmul;
+ long frametype;
+ long flushes;
+ long bitdepth;
+ long exttrigger;
+ long exttriggerpol;
+
+ double tempslope;
+ double tempintercept;
+
+ long grabrowcount;
+ long grabrowcounttot;
+ long grabrowindex;
+ long grabrowwidth;
+ long grabrowbatchsize;
+ long grabrowbufferindex;
+ long flushcountbeforefirstrow;
+ long flushcountafterlastrow;
+
+ unsigned short *gbuf;
+} flicamdata_t;
+
+extern const fliccdinfo_t knowndev[];
+
+long fli_camera_open(flidev_t dev);
+long fli_camera_close(flidev_t dev);
+long fli_camera_command(flidev_t dev, int cmd, int argc, ...);
+
+#endif /* _LIBFLI_CAMERA_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-debug.c b/kstars/kstars/indi/fli/libfli-debug.c
new file mode 100644
index 00000000..203274b3
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-debug.c
@@ -0,0 +1,120 @@
+/*
+
+ 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 <syslog.h>
+#include <stdarg.h>
+
+#include "libfli-libfli.h"
+
+int sysloglevel(int level)
+{
+ switch (level)
+ {
+ case FLIDEBUG_INFO:
+ return LOG_INFO;
+ break;
+
+ case FLIDEBUG_WARN:
+ return LOG_WARNING;
+ break;
+
+ case FLIDEBUG_FAIL:
+ return LOG_ERR;
+ break;
+
+ case FLIDEBUG_ALL:
+ return LOG_EMERG | LOG_ALERT | LOG_CRIT | LOG_ERR | LOG_WARNING |
+ LOG_NOTICE | LOG_INFO | LOG_DEBUG;
+ break;
+ }
+
+ return 0;
+}
+
+int debugopen(char *host)
+{
+ openlog("libfli", LOG_PID , LOG_USER);
+
+ return 0;
+}
+
+int debugclose(void)
+{
+ closelog();
+
+ return 0;
+}
+
+void debug(int level, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vsyslog(sysloglevel(level), format, ap);
+ va_end(ap);
+
+ return;
+}
+
+
+void setdebuglevel(char *host, int level)
+{
+ static int open = 0;
+
+ if (level == 0)
+ {
+ debugclose();
+ open = 0;
+ return;
+ }
+
+ if (open == 0)
+ {
+ debugopen(host);
+ open = 1;
+ }
+
+ setlogmask(LOG_UPTO(sysloglevel(level)));
+
+ return;
+}
diff --git a/kstars/kstars/indi/fli/libfli-debug.h b/kstars/kstars/indi/fli/libfli-debug.h
new file mode 100644
index 00000000..775244ae
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-debug.h
@@ -0,0 +1,53 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_DEBUG_H_
+#define _LIBFLI_DEBUG_H_
+
+/* Debug functions */
+int debugclose(void);
+int debugopen(char *host);
+void debug(int level, const char *format, ...);
+void setdebuglevel(char *host, int level);
+
+#endif /* _LIBFLI_DEBUG_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-filter-focuser.c b/kstars/kstars/indi/fli/libfli-filter-focuser.c
new file mode 100644
index 00000000..ef4afb8e
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-filter-focuser.c
@@ -0,0 +1,625 @@
+/*
+
+ 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
+
+*/
+
+#ifdef WIN32
+#include <winsock.h>
+#else
+#include <sys/param.h>
+#include <netinet/in.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <stdarg.h>
+
+#include "libfli-libfli.h"
+#include "libfli-mem.h"
+#include "libfli-debug.h"
+#include "libfli-filter-focuser.h"
+
+/*
+Array of filterwheel info
+ Pos = # of filters
+ Off = Offset of 0 filter from magnetic stop,
+ X - y = number of steps from filter x to filter y
+*/
+static const wheeldata_t wheeldata[] =
+{
+ /* POS OFF 0-1 1-2 2-3 3-4 4-5 5-6 6-7 7-8 8-9 9-A A-B B-C C-D D-E F-F F-0 */
+ { 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 1, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 2, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 3, 48, { 80, 80, 80, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 4, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 5, 0, { 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 6, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 7, 14, { 34, 34, 35, 34, 34, 35, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 8, 18, { 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 9, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {10, 0, { 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0} },
+ {11, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {12, 6,{ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0} },
+ {13, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {14, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {15, 0, { 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48} },
+};
+
+static long fli_stepmotor(flidev_t dev, long steps);
+static long fli_getsteppos(flidev_t dev, long *pos);
+static long fli_setfilterpos(flidev_t dev, long pos);
+
+
+long fli_filter_focuser_open(flidev_t dev)
+{
+#define FWSTRING "Filter Wheel (%ld position)"
+#define FOCSTRING "Focuser"
+#define MODEL_LEN (sizeof(FWSTRING) + 30)
+ int err = 0;
+ unsigned long ndev;
+ long rlen, wlen;
+ unsigned short buf[16];
+ flifilterdata_t *fdata = NULL;
+
+ CHKDEVICE(dev);
+
+ DEVICE->io_timeout = 1000;
+
+ wlen = 2;
+ rlen = 2;
+ buf[0] = htons(0x8000);
+ IO(dev, buf, &wlen, &rlen);
+ if (ntohs(buf[0]) != 0x8000)
+ {
+ debug(FLIDEBUG_WARN, "Invalid echo, device not recognized, got %04x instead of %04x.", ntohs(buf[0]), 0x8000);
+ err = -ENODEV;
+ goto done;
+ }
+
+ wlen = 2;
+ rlen = 2;
+ buf[0] = htons(0x8001);
+ IO(dev, buf, &wlen, &rlen);
+ DEVICE->devinfo.fwrev = ntohs(buf[0]);
+ if ((DEVICE->devinfo.fwrev & 0xff00) != 0x8000)
+ {
+ debug(FLIDEBUG_WARN, "Invalid echo, device not recognized.");
+ err = -ENODEV;
+ goto done;
+ }
+
+ if ((DEVICE->device_data = xmalloc(sizeof(flifilterdata_t))) == NULL)
+ {
+ err = -ENOMEM;
+ goto done;
+ }
+ fdata = DEVICE->device_data;
+ fdata->numslots = 0;
+ fdata->stepspersec = 100;
+ fdata->currentslot = -1;
+
+ if (DEVICE->devinfo.fwrev == 0x8001) /* Old level of firmware */
+ {
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+
+ debug(FLIDEBUG_INFO, "Device is old fashioned filter wheel.");
+ fdata->numslots = 5;
+
+ /* FIX: should model info be set first? */
+ return 0;
+ }
+
+ debug(FLIDEBUG_INFO, "New version of hardware found.");
+ wlen = 2;
+ rlen = 2;
+ buf[0] = htons(0x8002);
+ IO(dev, buf, &wlen, &rlen);
+ ndev = ntohs(buf[0]);
+
+ if ((ndev & 0xff00) != 0x8000)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+
+ if ((DEVICE->devinfo.model = (char *)xmalloc(MODEL_LEN)) == NULL)
+ {
+ debug(FLIDEBUG_FAIL, "Could not allocate memory for model information.");
+ err = -ENOMEM;
+ goto done;
+ }
+
+ ndev &= 0x00ff;
+
+ /* switch based on the jumper settings on the filter/focuser dongle, determines how many slots in the filter wheel */
+ switch (ndev)
+ {
+ case 0x00:
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ fdata->numslots = 5;
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+ case 0x01:
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ fdata->numslots = 3;
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+ case 0x02:
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ fdata->numslots = 7;
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+ case 0x03:
+ fdata->numslots = 8;
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+ case 0x04:
+ fdata->numslots = 15;
+ fdata->stepspersec= 16;/* // 1/.06 */
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+
+ case 0x05:
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ fdata->numslots = 12;
+ fdata->stepspersec= 16; /*// 1/.06*/
+
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+ case 0x06:
+ fdata->numslots = 10;
+ fdata->stepspersec= 16; /*// 1/.06*/
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+
+ case 0x07:
+ if (DEVICE->devinfo.type != FLIDEVICE_FOCUSER)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FOCSTRING);
+ break;
+
+ default:
+ err = -ENODEV;
+ goto done;
+ }
+
+ done:
+
+ if (err)
+ {
+ if (DEVICE->devinfo.model != NULL)
+ {
+ xfree(DEVICE->devinfo.model);
+ DEVICE->devinfo.model = NULL;
+ }
+
+ if (DEVICE->device_data != NULL)
+ {
+ xfree(DEVICE->device_data);
+ DEVICE->device_data = NULL;
+ }
+
+ return err;
+ }
+
+ debug(FLIDEBUG_INFO, "Found a %ld slot filter wheel or a focuser.",
+ fdata->numslots);
+
+#undef FWSTRING
+#undef FOCSTRING
+#undef MODEL_LEN
+
+ return 0;
+}
+
+long fli_filter_focuser_close(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ if (DEVICE->devinfo.model != NULL)
+ {
+ xfree(DEVICE->devinfo.model);
+ DEVICE->devinfo.model = NULL;
+ }
+
+ if (DEVICE->device_data != NULL)
+ {
+ xfree(DEVICE->device_data);
+ DEVICE->device_data = NULL;
+ }
+
+ return 0;
+}
+
+long fli_filter_command(flidev_t dev, int cmd, int argc, ...)
+{
+ flifilterdata_t *fdata;
+ long r;
+ va_list ap;
+
+ va_start(ap, argc);
+ CHKDEVICE(dev);
+ fdata = DEVICE->device_data;
+
+ switch (cmd)
+ {
+ case FLI_SET_FILTER_POS:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long pos;
+
+ pos = *va_arg(ap, long *);
+ r = fli_setfilterpos(dev, pos);
+ }
+ break;
+
+ case FLI_GET_FILTER_POS:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *cslot;
+
+ cslot = va_arg(ap, long *);
+ *cslot = fdata->currentslot;
+ r = 0;
+ }
+ break;
+
+ case FLI_GET_FILTER_COUNT:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *nslots;
+
+ nslots = va_arg(ap, long *);
+ *nslots = fdata->numslots;
+ r = 0;
+ }
+ break;
+
+ case FLI_STEP_MOTOR:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *steps;
+
+ steps = va_arg(ap, long *);
+ r = fli_stepmotor(dev, *steps);
+ }
+ break;
+
+ case FLI_GET_STEPPER_POS:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *pos;
+
+ pos = va_arg(ap, long *);
+ r = fli_getsteppos(dev, pos);
+ }
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+
+ va_end(ap);
+
+ return r;
+}
+
+long fli_focuser_command(flidev_t dev, int cmd, int argc, ...)
+{
+ long r;
+ va_list ap;
+
+ va_start(ap, argc);
+ CHKDEVICE(dev);
+
+ switch (cmd)
+ {
+ case FLI_STEP_MOTOR:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *steps;
+
+ steps = va_arg(ap, long *);
+ r = fli_stepmotor(dev, *steps);
+ }
+ break;
+
+ case FLI_GET_STEPPER_POS:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *pos;
+
+ pos = va_arg(ap, long *);
+ r = fli_getsteppos(dev, pos);
+ }
+ break;
+
+ case FLI_HOME_FOCUSER:
+ if (argc != 0)
+ r = -EINVAL;
+ else
+ r = fli_setfilterpos(dev, FLI_FILTERPOSITION_HOME);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+
+ va_end(ap);
+
+ return r;
+}
+
+static long fli_stepmotor(flidev_t dev, long steps)
+{
+ flifilterdata_t *fdata;
+ long dir, timeout, move, stepsleft;
+ long rlen,wlen;
+ unsigned short buf[16];
+ clock_t begin;
+
+ if (steps == 0)
+ return 0;
+
+ fdata = DEVICE->device_data;
+
+ dir = steps;
+ steps = abs(steps);
+ while (steps > 0)
+ {
+ if (steps > 2048)
+ move = 2048;
+ else
+ move = steps;
+
+ debug(FLIDEBUG_INFO, "Stepping %d steps.", move);
+
+ steps -= move;
+ timeout = (move / fdata->stepspersec) + 2;
+
+ rlen = 2;
+ wlen = 2;
+ if (dir < 0)
+ {
+ buf[0] = htons((unsigned short) (0xa000 | (unsigned short) move));
+ IO(dev, buf, &wlen, &rlen);
+ if ((ntohs(buf[0]) & 0xf000) != 0xa000)
+ {
+ debug(FLIDEBUG_WARN, "Invalid echo.");
+ return -EIO;
+ }
+ }
+ else
+ {
+ buf[0] = htons((unsigned short) (0x9000 | (unsigned short) move));
+ IO(dev, buf, &wlen, &rlen);
+ if ((ntohs(buf[0]) & 0xf000) != 0x9000)
+ {
+ debug(FLIDEBUG_WARN, "Invalid echo.");
+ return -EIO;
+ }
+ }
+
+ begin = clock();
+ stepsleft = 0;
+ while (stepsleft != 0x7000)
+ {
+ buf[0] = htons(0x7000);
+ IO(dev, buf, &wlen, &rlen);
+ stepsleft = ntohs(buf[0]);
+
+ if (((clock() - begin) / CLOCKS_PER_SEC) > timeout)
+ {
+ debug(FLIDEBUG_WARN, "A device timeout has occurred.");
+ return -EIO;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static long fli_getsteppos(flidev_t dev, long *pos)
+{
+ long poslow, poshigh;
+ long rlen, wlen;
+ unsigned short buf[16];
+
+ rlen = 2; wlen = 2;
+ buf[0] = htons(0x6000);
+ IO(dev, buf, &wlen, &rlen);
+ poslow = ntohs(buf[0]);
+ if ((poslow & 0xf000) != 0x6000)
+ return -EIO;
+
+ buf[0] = htons(0x6001);
+ IO(dev, buf, &wlen, &rlen);
+ poshigh = ntohs(buf[0]);
+ if ((poshigh & 0xf000) != 0x6000)
+ return -EIO;
+
+ if ((poshigh & 0x0080) > 0)
+ {
+ *pos = ((~poslow) & 0xff) + 1;
+ *pos += (256 * ((~poshigh) & 0xff));
+ *pos = -(*pos);
+ }
+ else
+ {
+ *pos = (poslow & 0xff) + 256 * (poshigh & 0xff);
+ }
+ return 0;
+}
+
+
+static long fli_setfilterpos(flidev_t dev, long pos)
+{
+ flifilterdata_t *fdata;
+ long rlen, wlen;
+ unsigned short buf[16];
+ long move, i, steps;
+
+ fdata = DEVICE->device_data;
+
+ if (pos == FLI_FILTERPOSITION_HOME)
+ fdata->currentslot = FLI_FILTERPOSITION_HOME;
+
+ if (fdata->currentslot < 0)
+ {
+ debug(FLIDEBUG_INFO, "Home filter wheel/focuser.");
+ /* //set the timeout*/
+ DEVICE->io_timeout = (DEVICE->devinfo.type == FLIDEVICE_FILTERWHEEL ? 5000 : 30000);
+ /*//10,12,15 pos filterwheel needs a longer timeout t*/
+ if(fdata->numslots == 12||fdata->numslots == 10)
+ {
+ DEVICE->io_timeout = 120000;
+ }
+ if(fdata->numslots == 15)
+ {
+ DEVICE->io_timeout = 200000;
+ }
+
+ wlen = 2;
+ rlen = 2;
+ buf[0] = htons(0xf000);
+ IO(dev, buf, &wlen, &rlen);
+ if (ntohs(buf[0]) != 0xf000)
+ return -EIO;
+
+ DEVICE->io_timeout = 1000;
+
+ debug(FLIDEBUG_INFO, "Moving %d steps to home position.",
+ wheeldata[fdata->numslots].n_offset);
+
+ COMMAND(fli_stepmotor(dev, - (wheeldata[fdata->numslots].n_offset)));
+ fdata->currentslot = 0;
+ }
+
+ if (pos == FLI_FILTERPOSITION_HOME)
+ return 0;
+
+ if (pos >= fdata->numslots)
+ {
+ debug(FLIDEBUG_WARN, "Requested slot (%d) exceeds number of slots.", pos);
+ return -EINVAL;
+ }
+
+ if (pos == fdata->currentslot)
+ return 0;
+
+ move = pos - fdata->currentslot;
+
+ if (move < 0)
+ move += fdata->numslots;
+
+ steps = 0;
+ for (i=0; i < move; i++)
+ steps += wheeldata[fdata->numslots].n_steps[i % fdata->numslots];
+
+ debug(FLIDEBUG_INFO, "Move filter wheel %d steps.", steps);
+
+ COMMAND(fli_stepmotor(dev, - (steps)));
+ fdata->currentslot = pos;
+
+ return 0;
+}
diff --git a/kstars/kstars/indi/fli/libfli-filter-focuser.h b/kstars/kstars/indi/fli/libfli-filter-focuser.h
new file mode 100644
index 00000000..dc50e4e9
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-filter-focuser.h
@@ -0,0 +1,74 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _FLI_FILTER_FOCUSER_H_
+#define _FLI_FILTER_FOCUSER_H_
+
+#define FLI_FILTERPOSITION_HOME (-1)
+
+/* Filter wheel and focuser parameters */
+typedef struct {
+ long numslots;
+ long stepspersec;
+ long currentslot;
+} flifilterdata_t;
+
+typedef struct {
+ int n_pos;
+ int n_offset;
+ int n_steps[16];
+} wheeldata_t;
+
+long fli_filter_focuser_open(flidev_t dev);
+#define fli_filter_open fli_filter_focuser_open
+#define fli_focuser_open fli_filter_focuser_open
+
+long fli_filter_focuser_close(flidev_t dev);
+#define fli_filter_close fli_filter_focuser_close
+#define fli_focuser_close fli_filter_focuser_close
+
+long fli_filter_command(flidev_t dev, int cmd, int argc, ...);
+long fli_focuser_command(flidev_t dev, int cmd, int argc, ...);
+
+
+#endif /* _FLI_FILTER_FOCUSER_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-libfli.h b/kstars/kstars/indi/fli/libfli-libfli.h
new file mode 100644
index 00000000..1a497d1d
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-libfli.h
@@ -0,0 +1,199 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_LIBFLI_H_
+#define _LIBFLI_LIBFLI_H_
+
+#include <string.h>
+
+#ifdef WIN32
+#define LIBFLIAPI __declspec(dllexport) long __stdcall
+#endif
+
+#include "libfli.h"
+#include "libfli-sys.h"
+#include "libfli-debug.h"
+
+#define __STRINGIFY(x) ___STRINGIFY(x)
+#define ___STRINGIFY(x) #x
+
+#define __LIBFLIVER_MAJOR__ 1
+#define __LIBFLIVER__ __STRINGIFY(__LIBFLIVER_MAJOR__) "." \
+ __STRINGIFY(__LIBFLI_MINOR__)
+
+#define CHKDEVICE(xdev) \
+ do { \
+ if((xdev < 0) || (xdev >= MAX_OPEN_DEVICES)) \
+ { \
+ debug(FLIDEBUG_WARN, \
+ "Attempt to use a device out of range (%d)", xdev); \
+ return -EINVAL; \
+ } \
+ if(devices[xdev] == NULL) \
+ { \
+ debug(FLIDEBUG_WARN, \
+ "Attempt to use a NULL device (%d)", xdev); \
+ return -EINVAL; \
+ } \
+ } while(0)
+
+#define CHKFUNCTION(func) \
+ do { \
+ if(func == NULL) \
+ { \
+ debug(FLIDEBUG_WARN, \
+ "Attempt to use a NULL function (" #func ")"); \
+ return -EINVAL; \
+ } \
+ } while(0)
+
+#define IO(dev, buf, wlen, rlen) \
+ do { \
+ int err; \
+ if((err = devices[dev]->fli_io(dev, buf, wlen, rlen))) \
+ { \
+ debug(FLIDEBUG_WARN, "Communication error: %d [%s]", \
+ err, strerror(-err)); \
+ return err; \
+ } \
+ } while(0)
+
+#define COMMAND(function) \
+ do { \
+ int err; \
+ if((err = function)) \
+ { \
+ debug(FLIDEBUG_WARN, \
+ "Function `" #function "' failed, error: %d [%s]", \
+ err, strerror(-err)); \
+ return err; \
+ } \
+ } while(0)
+
+#define FLIUSB_VENDORID 0xf18
+#define FLIUSB_CAM_ID 0x02
+#define FLIUSB_FILTER_ID 0x07
+#define FLIUSB_FOCUSER_ID 0x06
+
+#define MAX_OPEN_DEVICES (32)
+#define MAX_SEARCH_LIST (16)
+
+/* Common device information */
+typedef struct {
+ long type;
+ long fwrev;
+ long hwrev;
+ long devid;
+ long serno;
+ char *model;
+ char *devnam;
+} flidevinfo_t;
+
+/* A specific device instance */
+typedef struct {
+ char *name; /* The device name */
+ long domain; /* The device's domain */
+ flidevinfo_t devinfo; /* Device information */
+ long io_timeout; /* Timeout in msec for all I/O */
+ void *io_data; /* For holding I/O specific data */
+ void *device_data; /* For holding device specific data */
+ void *sys_data; /* For holding system specific data */
+
+ /* System-specific functions */
+ long (*fli_lock)(flidev_t dev);
+ long (*fli_unlock)(flidev_t dev);
+
+ /* Domain-specific functions */
+ long (*fli_io)(flidev_t dev, void *buf, long *wlen, long *rlen);
+
+ /* Device-specific functions */
+ long (*fli_open)(flidev_t dev);
+ long (*fli_close)(flidev_t dev);
+ long (*fli_command)(flidev_t dev, int cmd, int argc, ...);
+} flidevdesc_t;
+
+extern const char* version;
+
+extern flidevdesc_t *devices[MAX_OPEN_DEVICES];
+#define DEVICE devices[dev]
+
+/* Device commands, the format is FLI_COMMAND(<command name>, <number of args>) */
+#define FLI_COMMANDS \
+ FLI_COMMAND(FLI_NONE, 0) \
+ FLI_COMMAND(FLI_GET_PIXEL_SIZE, 2) \
+ FLI_COMMAND(FLI_GET_ARRAY_AREA, 4) \
+ FLI_COMMAND(FLI_GET_VISIBLE_AREA, 4) \
+ FLI_COMMAND(FLI_SET_EXPOSURE_TIME, 1) \
+ FLI_COMMAND(FLI_SET_IMAGE_AREA, 4) \
+ FLI_COMMAND(FLI_SET_HBIN, 1) \
+ FLI_COMMAND(FLI_SET_VBIN, 1) \
+ FLI_COMMAND(FLI_SET_FRAME_TYPE, 1) \
+ FLI_COMMAND(FLI_CANCEL_EXPOSURE, 0) \
+ FLI_COMMAND(FLI_GET_EXPOSURE_STATUS, 1) \
+ FLI_COMMAND(FLI_SET_TEMPERATURE, 1) \
+ FLI_COMMAND(FLI_GET_TEMPERATURE, 1) \
+ FLI_COMMAND(FLI_GRAB_ROW, 2) \
+ FLI_COMMAND(FLI_EXPOSE_FRAME, 0) \
+ FLI_COMMAND(FLI_FLUSH_ROWS, 2) \
+ FLI_COMMAND(FLI_SET_FLUSHES, 1) \
+ FLI_COMMAND(FLI_SET_BIT_DEPTH, 1) \
+ FLI_COMMAND(FLI_READ_IOPORT, 1) \
+ FLI_COMMAND(FLI_WRITE_IOPORT, 1) \
+ FLI_COMMAND(FLI_CONFIGURE_IOPORT, 1) \
+ FLI_COMMAND(FLI_CONTROL_SHUTTER, 1) \
+ FLI_COMMAND(FLI_CONTROL_BGFLUSH, 1) \
+ FLI_COMMAND(FLI_SET_FILTER_POS, 1) \
+ FLI_COMMAND(FLI_GET_FILTER_POS, 1) \
+ FLI_COMMAND(FLI_GET_FILTER_COUNT, 1) \
+ FLI_COMMAND(FLI_STEP_MOTOR, 1) \
+ FLI_COMMAND(FLI_GET_STEPPER_POS, 1) \
+ FLI_COMMAND(FLI_HOME_FOCUSER, 0)
+
+/* Enumerate the commands */
+enum {
+#define FLI_COMMAND(name, args) name,
+ FLI_COMMANDS
+#undef FLI_COMMAND
+};
+
+#endif /* _LIBFLI_LIBFLI_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-mem.c b/kstars/kstars/indi/fli/libfli-mem.c
new file mode 100644
index 00000000..f6bee1bc
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-mem.c
@@ -0,0 +1,203 @@
+/*
+
+ Copyright (c) 2000, 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 <stdlib.h>
+#include <string.h>
+
+#include "libfli-libfli.h"
+#include "libfli-mem.h"
+
+#define DEFAULT_NUM_POINTERS (1024)
+
+static struct {
+ void **pointers;
+ int total;
+ int used;
+} allocated = {NULL, 0, 0};
+
+void *xmalloc(size_t size)
+{
+ int i;
+ void *ptr;
+
+ if (allocated.used + 1 > allocated.total)
+ {
+ void **tmp;
+ int num;
+
+ num = (allocated.total == 0 ? DEFAULT_NUM_POINTERS : 2 * allocated.total);
+
+ if ((tmp = (void **)realloc(allocated.pointers,
+ num * sizeof(void **))) == NULL)
+ return NULL;
+
+ allocated.pointers = tmp;
+ memset(&allocated.pointers[allocated.total], 0, num * sizeof(void **));
+ allocated.total += num;
+ }
+
+ if ((ptr = malloc(size)) == NULL)
+ return NULL;
+
+ for (i = 0; i < allocated.total; i++)
+ {
+ if (allocated.pointers[i] == NULL)
+ break;
+ }
+
+ if (i == allocated.total)
+ {
+ /* This shouldn't happen */
+ debug(FLIDEBUG_WARN, "Internal memory allocation error");
+ free(ptr);
+
+ return NULL;
+ }
+
+ allocated.pointers[i] = ptr;
+ allocated.used++;
+
+ return ptr;
+}
+
+
+void *xcalloc(size_t nmemb, size_t size)
+{
+ void *ptr;
+
+ if ((ptr = xmalloc(nmemb * size)) == NULL)
+ return NULL;
+
+ memset(ptr, 0, nmemb * size);
+
+ return ptr;
+}
+
+void xfree(void *ptr)
+{
+ int i;
+
+ for (i = 0; i < allocated.total; i++)
+ {
+ if (allocated.pointers[i] == ptr)
+ {
+ free(ptr);
+ allocated.pointers[i] = NULL;
+ allocated.used--;
+
+ return;
+ }
+ }
+
+ debug(FLIDEBUG_WARN, "Attempting to free an invalid pointer");
+
+ return;
+}
+
+void *xrealloc(void *ptr, size_t size)
+{
+ int i;
+
+ for (i = 0; i < allocated.total; i++)
+ {
+ if (allocated.pointers[i] == ptr)
+ {
+ void *tmp;
+
+ if ((tmp = realloc(ptr, size)) == NULL)
+ return NULL;
+
+ allocated.pointers[i] = tmp;
+
+ return tmp;
+ }
+ }
+
+ debug(FLIDEBUG_WARN, "Attempting to realloc an invalid pointer");
+
+ return NULL;
+}
+
+int xfree_all(void)
+{
+ int i;
+ int freed = 0;
+
+ for (i = 0; i < allocated.total; i++)
+ {
+ if (allocated.pointers[i] != NULL)
+ {
+ free(allocated.pointers[i]);
+ allocated.pointers[i] = NULL;
+ allocated.used--;
+ freed++;
+ }
+ }
+
+ if (allocated.used != 0)
+ debug(FLIDEBUG_WARN, "Internal memory handling error");
+
+ if (allocated.pointers != NULL)
+ free(allocated.pointers);
+
+ allocated.pointers = NULL;
+ allocated.used = 0;
+ allocated.total = 0;
+
+ return freed;
+}
+
+char *xstrdup(const char *s)
+{
+ void *tmp;
+ size_t len;
+
+ len = strlen(s) + 1;
+
+ if ((tmp = xmalloc(len)) == NULL)
+ return NULL;
+
+ memcpy(tmp, s, len);
+
+ return tmp;
+}
diff --git a/kstars/kstars/indi/fli/libfli-mem.h b/kstars/kstars/indi/fli/libfli-mem.h
new file mode 100644
index 00000000..c016fc64
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-mem.h
@@ -0,0 +1,54 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_MEM_H_
+#define _LIBFLI_MEM_H_
+
+void *xmalloc(size_t size);
+void *xcalloc(size_t nmemb, size_t size);
+void xfree(void *ptr);
+void *xrealloc(void *ptr, size_t size);
+int xfree_all(void);
+char *xstrdup(const char *s);
+
+#endif /* _LIBFLI_MEM_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-parport.c b/kstars/kstars/indi/fli/libfli-parport.c
new file mode 100644
index 00000000..714e33eb
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-parport.c
@@ -0,0 +1,136 @@
+/*
+
+ 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/ioctl.h>
+#include <asm/param.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "libfli-libfli.h"
+#include "libfli-debug.h"
+#include "libfli-camera.h"
+
+#include "fli_ioctl.h"
+
+long unix_parportio_linux(flidev_t dev, void *buf, long *wlen, long *rlen)
+{
+ fli_unixio_t *io;
+ flicamdata_t *cam;
+ int err = 0, locked = 0;
+ long org_wlen = *wlen, org_rlen = *rlen;
+ int wto, rto, dto;
+ long ticks;
+
+ io = DEVICE->io_data;
+ cam = DEVICE->device_data;
+
+ if ((err = unix_fli_lock(dev)))
+ {
+ debug(FLIDEBUG_WARN, "Lock failed");
+ goto done;
+ }
+
+ locked = 1;
+
+ /* Convert timeout to jiffies */
+#ifdef HZ
+ ticks = HZ;
+#else
+ ticks = sysconf(_SC_CLK_TCK);
+#endif
+ wto = cam->writeto / 1000 * ticks;
+ rto = cam->readto / 1000 * ticks;
+ dto = cam->dirto / 1000 * ticks;
+
+ if (ioctl(io->fd, FLI_SET_WTO, &wto))
+ {
+ err = -errno;
+ goto done;
+ }
+
+ if (ioctl(io->fd, FLI_SET_DTO, &dto))
+ {
+ err = -errno;
+ goto done;
+ }
+
+ if (ioctl(io->fd, FLI_SET_RTO, &rto))
+ {
+ err = -errno;
+ goto done;
+ }
+
+ if ((*wlen = write(io->fd, buf, *wlen)) != org_wlen)
+ {
+ debug(FLIDEBUG_WARN, "write failed, only %d of %d bytes written",
+ *wlen, org_wlen);
+ err = -errno;
+ goto done;
+ }
+
+ if (*rlen > 0)
+ {
+ if ((*rlen = read(io->fd, buf, *rlen)) != org_rlen)
+ {
+ debug(FLIDEBUG_WARN, "read failed, only %d of %d bytes read",
+ *rlen, org_rlen);
+ err = -errno;
+ goto done;
+ }
+ }
+
+ done:
+
+ if (locked)
+ {
+ int r;
+
+ if ((r = unix_fli_unlock(dev)))
+ debug(FLIDEBUG_WARN, "Unlock failed");
+ if (err == 0)
+ err = r;
+ }
+
+ return err;
+}
diff --git a/kstars/kstars/indi/fli/libfli-parport.h b/kstars/kstars/indi/fli/libfli-parport.h
new file mode 100644
index 00000000..ab70c7a7
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-parport.h
@@ -0,0 +1,64 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_PARPORT_H_
+#define _LIBFLI_PARPORT_H_
+
+#if defined(__linux__)
+
+#define unix_parportio unix_parportio_linux
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
+
+#define unix_parportio NULL
+
+#else
+
+#define unix_parportio NULL
+#warning "Unknown system"
+
+#endif
+
+long unix_parportio_linux(flidev_t dev, void *buf, long *wlen, long *rlen);
+
+#endif /* _LIBFLI_PARPORT_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-serial.c b/kstars/kstars/indi/fli/libfli-serial.c
new file mode 100644
index 00000000..5b01e294
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-serial.c
@@ -0,0 +1,189 @@
+/*
+
+ 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/types.h>
+#include <sys/time.h>
+
+#include <termios.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libfli-libfli.h"
+#include "libfli-debug.h"
+#include "libfli-sys.h"
+#include "libfli-serial.h"
+
+long unix_serialio(flidev_t dev, void *buf, long *wlen, long *rlen)
+{
+ int err = 0, locked = 0, gotattr = 0;
+ long org_wlen = *wlen, org_rlen = *rlen;
+ struct termios old_termios, new_termios;
+ fli_unixio_t *io;
+
+ io = DEVICE->io_data;
+
+ if ((err = unix_fli_lock(dev)))
+ {
+ debug(FLIDEBUG_WARN, "Lock failed");
+ goto done;
+ }
+ locked = 1;
+
+ if (tcgetattr(io->fd, &old_termios))
+ {
+ err = -errno;
+ debug(FLIDEBUG_WARN, "tcgetattr() failed: %s", strerror(errno));
+ goto done;
+ }
+ gotattr = 1;
+
+ bzero(&new_termios, sizeof(struct termios));
+ new_termios.c_cflag = CS8 | CREAD | CLOCAL;
+ new_termios.c_cc[VMIN] = 1;
+ new_termios.c_cc[VTIME] = 0;
+
+ /* Set the input baud rate */
+ if (cfsetispeed(&new_termios, BAUDRATE))
+ {
+ err = -errno;
+ debug(FLIDEBUG_WARN, "cfsetispeed() failed: %s", strerror(errno));
+ goto done;
+ }
+ /* Set the output baud rate */
+ if (cfsetospeed(&new_termios, BAUDRATE))
+ {
+ err = -errno;
+ debug(FLIDEBUG_WARN, "cfsetospeed() failed: %s", strerror(errno));
+ goto done;
+ }
+
+ if (tcsetattr(io->fd, TCSANOW, &new_termios))
+ {
+ err = -errno;
+ /* FIX: Should this be FLIDEBUG_FAIL*/
+ debug(FLIDEBUG_WARN, "tcsetattr() failed: %s", strerror(errno));
+ goto done;
+ }
+
+ if ((*wlen = write(io->fd, buf, org_wlen)) != org_wlen)
+ {
+ err = -errno;
+ debug(FLIDEBUG_WARN, "write() failed, only %d of %d bytes written",
+ *wlen, org_wlen);
+ goto done;
+ }
+
+ if (tcdrain(io->fd))
+ {
+ err = -errno;
+ debug(FLIDEBUG_WARN, "tcdrain() failed: %s", strerror(errno));
+ goto done;
+ }
+
+ for (*rlen = 0; *rlen < org_rlen; )
+ {
+ ssize_t r;
+ fd_set readfds;
+ struct timeval timeout;
+
+ timeout.tv_sec = DEVICE->io_timeout / 1000;
+ timeout.tv_usec = (DEVICE->io_timeout % 1000) * 1000;
+
+ FD_ZERO(&readfds);
+ FD_SET(io->fd, &readfds);
+
+ switch (select(io->fd + 1, &readfds, NULL, NULL, &timeout))
+ {
+ case -1: /* An error occurred */
+ err = -errno;
+ debug(FLIDEBUG_WARN, "select() failed: %s", strerror(errno));
+ break;
+
+ case 0: /* A timeout occurred */
+ err = -ETIMEDOUT;
+ debug(FLIDEBUG_WARN, "A serial communication timeout occurred");
+ break;
+
+ default: /* There's some data to read */
+ if ((r = read(io->fd, buf + *rlen, org_rlen - *rlen)) <= 0)
+ {
+ err = -errno;
+ debug(FLIDEBUG_WARN, "read() failed, only %d of %d bytes read",
+ r, org_rlen - *rlen);
+ }
+ else
+ *rlen += r;
+ break;
+ }
+
+ if (err)
+ break;
+ }
+
+ done:
+
+ if (gotattr)
+ {
+ if (tcsetattr(io->fd, TCSANOW, &old_termios))
+ {
+ if (err == 0)
+ err = -errno;
+ debug(FLIDEBUG_WARN,
+ "tcsetattr() failed, could not restore terminal settings: %s",
+ strerror(errno));
+ }
+ }
+
+ if (locked)
+ {
+ int r;
+
+ if ((r = unix_fli_unlock(dev)))
+ debug(FLIDEBUG_WARN, "Unlock failed");
+ if (err == 0)
+ err = r;
+ }
+
+ return err;
+}
diff --git a/kstars/kstars/indi/fli/libfli-serial.h b/kstars/kstars/indi/fli/libfli-serial.h
new file mode 100644
index 00000000..d2456a56
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-serial.h
@@ -0,0 +1,51 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_SERIAL_H_
+#define _LIBFLI_SERIAL_H_
+
+#define BAUDRATE B1200
+
+long unix_serialio(flidev_t dev, void *buf, long *wlen, long *rlen);
+
+#endif /* _LIBFLI_SERIAL_H_ */
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);
+}
diff --git a/kstars/kstars/indi/fli/libfli-sys.h b/kstars/kstars/indi/fli/libfli-sys.h
new file mode 100644
index 00000000..a5d94bd5
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-sys.h
@@ -0,0 +1,108 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_SYS_H
+#define _LIBFLI_SYS_H
+
+#include <limits.h>
+
+#define LIBFLIAPI long
+
+#if defined(__linux__)
+
+#define __SYSNAME__ "Linux"
+#define __LIBFLI_MINOR__ 11
+#define USB_READ_SIZ_MAX 4096 /* Can only read a page at a time */
+#define _USE_FLOCK_
+#define PARPORT_GLOB "/dev/ccd*"
+#define USB_GLOB "/proc/bus/usb/*/*"
+#define SERIAL_GLOB "/dev/ttyS[0-9]*"
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+// FIXME - this does not actually work on OSX
+
+#define __SYSNAME__ "FreeBSD"
+#define __LIBFLI_MINOR__ 1
+#define USB_READ_SIZ_MAX (1024 *1024) /* 1 MB (This is arbitrary, but
+ * must be able to malloc this amount.)
+ */
+#define USB_GLOB "/dev/ugen*." __STRINGIFY(FLI_CMD_ENDPOINT)
+#define SERIAL_GLOB "/dev/cuaa*"
+
+#elif defined (__NetBSD__)
+
+#define __SYSNAME__ "NetBSD"
+#define __LIBFLI_MINOR__ 1
+#define USB_READ_SIZ_MAX (1024 *1024) /* 1 MB (This is arbitrary, but
+ * must be able to malloc this amount.)
+ */
+#define USB_GLOB "/dev/ugen*.0" __STRINGIFY(FLI_CMD_ENDPOINT)
+#define SERIAL_GLOB "/dev/dty0*"
+
+#else
+
+#define __SYSNAME__ "Unknown"
+#define __LIBFLI_MINOR__ 1
+#define USB_READ_SIZ_MAX 0
+#define USB_GLOB ""
+#define SERIAL_GLOB ""
+
+#warning "Unknown system"
+
+#endif
+
+typedef struct {
+ int fd;
+} fli_unixio_t;
+
+long unix_fli_connect(flidev_t dev, char *name, long domain);
+long unix_fli_disconnect(flidev_t dev);
+long unix_fli_lock(flidev_t dev);
+long unix_fli_unlock(flidev_t dev);
+long unix_fli_list(flidomain_t domain, char ***names);
+
+#define fli_connect unix_fli_connect
+#define fli_disconnect unix_fli_disconnect
+#define fli_list unix_fli_list
+
+#endif /* _LIBFLI_SYS_H */
diff --git a/kstars/kstars/indi/fli/libfli-usb-sys-bsd.c b/kstars/kstars/indi/fli/libfli-usb-sys-bsd.c
new file mode 100644
index 00000000..d1f6a2b0
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-usb-sys-bsd.c
@@ -0,0 +1,133 @@
+/*
+
+ 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/types.h>
+#include <dev/usb/usb.h>
+#include <sys/ioctl.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "libfli-libfli.h"
+#include "libfli-sys.h"
+#include "libfli-usb.h"
+
+long unix_usbverifydescriptor(flidev_t dev, fli_unixio_t *io)
+{
+ usb_device_descriptor_t usb_desc;
+ int r;
+
+ if ((r = read(io->fd, &usb_desc, sizeof(usb_device_descriptor_t))) !=
+ sizeof(usb_device_descriptor_t))
+ {
+ debug(FLIDEBUG_FAIL, "linux_usbverifydescriptor(): Could not read descriptor.");
+ return -EIO;
+ }
+ else
+ {
+ debug(FLIDEBUG_INFO, "USB device descriptor:");
+ if(usb_desc.idVendor != 0x0f18)
+ {
+ debug(FLIDEBUG_FAIL, "linux_usbverifydescriptor(): Not a FLI device!");
+ return -ENODEV;
+ }
+
+ switch(DEVICE->domain)
+ {
+ case FLIDOMAIN_USB:
+ if(usb_desc.idProduct != 0x0002)
+ {
+ return -ENODEV;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ DEVICE->devinfo.fwrev = usb_desc.bcdDevice;
+ }
+
+ return 0;
+}
+
+long bsd_bulkwrite(flidev_t dev, void *buf, long *wlen)
+{
+ fli_unixio_t *io;
+ long org_wlen = *wlen;
+ int to;
+
+ io = DEVICE->io_data;
+ to = DEVICE->io_timeout;
+
+ if (ioctl(io->fd, USB_SET_TIMEOUT, &to) == -1)
+ return -errno;
+
+ *wlen = write(io->fd, buf, *wlen);
+
+ if (*wlen != org_wlen)
+ return -errno;
+ else
+ return 0;
+}
+
+long bsd_bulkread(flidev_t dev, void *buf, long *rlen)
+{
+ fli_unixio_t *io;
+ long org_rlen = *rlen;
+ int to;
+
+ io = DEVICE->io_data;
+ to = DEVICE->io_timeout;
+
+ if (ioctl(io->fd, USB_SET_TIMEOUT, &to) == -1)
+ return -errno;
+
+ *rlen = read(io->fd, buf, *rlen);
+
+ if (*rlen != org_rlen)
+ return -errno;
+ else
+ return 0;
+}
diff --git a/kstars/kstars/indi/fli/libfli-usb-sys-linux.c b/kstars/kstars/indi/fli/libfli-usb-sys-linux.c
new file mode 100644
index 00000000..d35858a4
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-usb-sys-linux.c
@@ -0,0 +1,225 @@
+/*
+
+ 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+
+#include <errno.h>
+
+#include "libfli-libfli.h"
+#include "libfli-sys.h"
+#include "libfli-usb.h"
+
+#define USB_DIR_OUT 0 /* to device */
+#define USB_DIR_IN 0x80 /* to host */
+#define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int)
+#define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer)
+#define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int)
+#define IOCTL_USB_RESET _IO('U', 20)
+
+/* Device descriptor */
+typedef struct
+{
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+ u_int16_t bcdUSB;
+ u_int8_t bDeviceClass;
+ u_int8_t bDeviceSubClass;
+ u_int8_t bDeviceProtocol;
+ u_int8_t bMaxPacketSize0;
+ u_int16_t idVendor;
+ u_int16_t idProduct;
+ u_int16_t bcdDevice;
+ u_int8_t iManufacturer;
+ u_int8_t iProduct;
+ u_int8_t iSerialNumber;
+ u_int8_t bNumConfigurations;
+} usb_device_descriptor __attribute__ ((packed));
+
+struct usbdevfs_bulktransfer {
+ unsigned int ep;
+ unsigned int len;
+ unsigned int timeout; /* in milliseconds */
+ void *data;
+};
+
+long linux_usb_reset(flidev_t dev);
+
+long unix_usbverifydescriptor(flidev_t dev, fli_unixio_t *io)
+{
+ usb_device_descriptor usb_desc;
+ int r;
+
+ if ((r = read(io->fd, &usb_desc, sizeof(usb_device_descriptor))) !=
+ sizeof(usb_device_descriptor))
+ {
+ debug(FLIDEBUG_FAIL, "linux_usbverifydescriptor(): Could not read descriptor.");
+ return -EIO;
+ }
+ else
+ {
+ debug(FLIDEBUG_INFO, "USB device descriptor:");
+ if(usb_desc.idVendor != 0x0f18)
+ {
+ debug(FLIDEBUG_FAIL, "linux_usbverifydescriptor(): Not a FLI device!");
+ return -ENODEV;
+ }
+
+ switch(DEVICE->domain)
+ {
+ case FLIDOMAIN_USB:
+ if( (usb_desc.idProduct != 0x0002) &&
+ (usb_desc.idProduct != 0x0006) &&
+ (usb_desc.idProduct != 0x0007) ) {
+ return -ENODEV;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ DEVICE->devinfo.fwrev = usb_desc.bcdDevice;
+ }
+
+ return 0;
+}
+
+static long linux_bulktransfer(flidev_t dev, int ep, void *buf, long *len)
+{
+ fli_unixio_t *io;
+ unsigned int iface = 0;
+ struct usbdevfs_bulktransfer bulk;
+ unsigned int tbytes = 0;
+ long bytes;
+
+/* This section of code has been modified since the Linux kernel has (had)
+ a 4096 byte limit (kernel page size) on the IOCTL for data transfer.
+ We ran into a problem when the CCD camera became large and the data
+ transfer requirements grew. */
+
+ io = DEVICE->io_data;
+
+ /* Claim the interface */
+ if (ioctl(io->fd, USBDEVFS_CLAIMINTERFACE, &iface))
+ return -errno;
+
+/* #define _DEBUG */
+
+#ifdef _DEBUG
+
+ if ((ep & 0xf0) == 0) {
+ char buffer[1024];
+ int i;
+
+ sprintf(buffer, "OUT %6ld: ", *len);
+ for (i = 0; i < ((*len > 16)?16:*len); i++) {
+ sprintf(buffer + strlen(buffer), "%02x ", ((unsigned char *) buf)[i]);
+ }
+
+ debug(FLIDEBUG_INFO, buffer);
+ }
+
+#endif /* _DEBUG */
+
+ while (tbytes < (unsigned) *len) {
+ bulk.ep = ep;
+ bulk.len = ((*len - tbytes) > 4096)?4096:(*len - tbytes);
+ bulk.timeout = DEVICE->io_timeout;
+ bulk.data = buf + tbytes;
+
+ /* This ioctl return the number of bytes transfered */
+ if((bytes = ioctl(io->fd, USBDEVFS_BULK, &bulk)) != (long) bulk.len)
+ break;
+
+ tbytes += bytes;
+ }
+
+#ifdef _DEBUG
+
+ if ((ep & 0xf0) != 0) {
+ char buffer[1024];
+ int i;
+
+ sprintf(buffer, " IN %6ld: ", *len);
+ for (i = 0; i < ((*len > 16)?16:*len); i++) {
+ sprintf(buffer + strlen(buffer), "%02x ", ((unsigned char *) buf)[i]);
+ }
+
+ debug(FLIDEBUG_INFO, buffer);
+ }
+
+#endif /* _DEBUG */
+
+ /* Release the interface */
+/* if (ioctl(io->fd, USBDEVFS_RELEASEINTERFACE, &iface))
+ return -errno; */
+
+ if ((unsigned) *len != tbytes)
+ return -errno;
+ else
+ return 0;
+}
+
+long linux_bulkwrite(flidev_t dev, void *buf, long *wlen)
+{
+ return linux_bulktransfer(dev, FLI_CMD_ENDPOINT | USB_DIR_OUT, buf, wlen);
+}
+
+long linux_bulkread(flidev_t dev, void *buf, long *rlen)
+{
+ return linux_bulktransfer(dev, FLI_CMD_ENDPOINT | USB_DIR_IN, buf, rlen);
+}
+
+long linux_usb_reset(flidev_t dev)
+{
+ fli_unixio_t *io;
+
+ io = DEVICE->io_data;
+
+ return (ioctl(io->fd, IOCTL_USB_RESET, NULL));
+
+}
diff --git a/kstars/kstars/indi/fli/libfli-usb-sys-null.c b/kstars/kstars/indi/fli/libfli-usb-sys-null.c
new file mode 100644
index 00000000..2b73b202
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-usb-sys-null.c
@@ -0,0 +1,67 @@
+/*
+
+ 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/types.h>
+#include <sys/ioctl.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "libfli-libfli.h"
+#include "libfli-sys.h"
+#include "libfli-usb.h"
+
+long null_bulkwrite(flidev_t dev, void *buf, long *wlen)
+{
+ return -errno;
+}
+
+long null_bulkread(flidev_t dev, void *buf, long *rlen)
+{
+ return -errno;
+}
+
+long unix_usbverifydescriptor(flidev_t dev, fli_unixio_t *io)
+{
+ return -errno;
+}
diff --git a/kstars/kstars/indi/fli/libfli-usb.c b/kstars/kstars/indi/fli/libfli-usb.c
new file mode 100644
index 00000000..b816d6b2
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-usb.c
@@ -0,0 +1,94 @@
+/*
+
+ 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 <errno.h>
+
+#include "libfli-libfli.h"
+#include "libfli-debug.h"
+#include "libfli-sys.h"
+#include "libfli-usb.h"
+
+long unix_usbio(flidev_t dev, void *buf, long *wlen, long *rlen)
+{
+ int err = 0, locked = 0;
+ long org_wlen = *wlen, org_rlen = *rlen;
+
+ if ((err = unix_fli_lock(dev)))
+ {
+ debug(FLIDEBUG_WARN, "Lock failed");
+ goto done;
+ }
+
+ locked = 1;
+
+ if ((err = unix_bulkwrite(dev, buf, wlen)))
+ {
+ debug(FLIDEBUG_WARN, "Bulkwrite failed, only %d of %d bytes written",
+ *wlen, org_wlen);
+ goto done;
+ }
+
+ if (*rlen > 0)
+ {
+ if ((err = unix_bulkread(dev, buf, rlen)))
+ {
+ debug(FLIDEBUG_WARN, "Bulkread failed, only %d of %d bytes read",
+ *rlen, org_rlen);
+ goto done;
+ }
+ }
+
+ done:
+
+ if (locked)
+ {
+ int r;
+
+ if ((r = unix_fli_unlock(dev)))
+ debug(FLIDEBUG_WARN, "Unlock failed");
+ if (err == 0)
+ err = r;
+ }
+
+ return err;
+}
diff --git a/kstars/kstars/indi/fli/libfli-usb.h b/kstars/kstars/indi/fli/libfli-usb.h
new file mode 100644
index 00000000..f982b4f8
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-usb.h
@@ -0,0 +1,69 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_USB_H_
+#define _LIBFLI_USB_H_
+
+#define FLI_CMD_ENDPOINT 2
+
+#if defined(__linux__)
+#define unix_bulkwrite linux_bulkwrite
+#define unix_bulkread linux_bulkread
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
+#define unix_bulkwrite bsd_bulkwrite
+#define unix_bulkread bsd_bulkread
+
+#else
+#define unix_bulkwrite null_bulkwrite
+#define unix_bulkread null_bulkread
+
+#warning "using null I/O operations!"
+#endif
+
+long unix_bulkwrite(flidev_t dev, void *buf, long *wlen);
+long unix_bulkread(flidev_t dev, void *buf, long *rlen);
+long unix_usbio(flidev_t dev, void *buf, long *wlen, long *rlen);
+long unix_usbverifydescriptor(flidev_t dev, fli_unixio_t *io);
+
+#endif /* _LIBFLI_USB_H_ */
diff --git a/kstars/kstars/indi/fli/libfli.c b/kstars/kstars/indi/fli/libfli.c
new file mode 100644
index 00000000..68df7945
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli.c
@@ -0,0 +1,1383 @@
+/*
+
+ Copyright (c) 2000, 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 <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "libfli-libfli.h"
+#include "libfli-mem.h"
+#include "libfli-debug.h"
+
+static long devalloc(flidev_t *dev);
+static long devfree(flidev_t dev);
+static long fli_open(flidev_t *dev, char *name, long domain);
+static long fli_close(flidev_t dev);
+static long fli_freelist(char **names);
+
+flidevdesc_t *devices[MAX_OPEN_DEVICES] = {NULL,};
+
+const char* version =
+"FLI Software Development Library for " __SYSNAME__ " " __LIBFLIVER__;
+
+static long devalloc(flidev_t *dev)
+{
+ int i;
+
+ if (dev == NULL)
+ return -EINVAL;
+
+ for (i = 0; i < MAX_OPEN_DEVICES; i++)
+ if (devices[i] == NULL)
+ break;
+
+ if (i == MAX_OPEN_DEVICES)
+ return -ENODEV;
+
+ if ((devices[i] =
+ (flidevdesc_t *)xcalloc(1, sizeof(flidevdesc_t))) == NULL)
+ return -ENOMEM;
+
+ *dev = i;
+
+ return 0;
+}
+
+static long devfree(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ if (DEVICE->io_data != NULL)
+ {
+ debug(FLIDEBUG_WARN, "close didn't free io_data (not NULL)");
+ xfree(DEVICE->io_data);
+ DEVICE->io_data = NULL;
+ }
+ if (DEVICE->device_data != NULL)
+ {
+ debug(FLIDEBUG_WARN, "close didn't free device_data (not NULL)");
+ xfree(DEVICE->device_data);
+ DEVICE->device_data = NULL;
+ }
+ if (DEVICE->sys_data != NULL)
+ {
+ debug(FLIDEBUG_WARN, "close didn't free sys_data (not NULL)");
+ xfree(DEVICE->sys_data);
+ DEVICE->sys_data = NULL;
+ }
+
+ if (DEVICE->name != NULL)
+ {
+ xfree(DEVICE->name);
+ DEVICE->name = NULL;
+ }
+
+ xfree(DEVICE);
+ DEVICE = NULL;
+
+ return 0;
+}
+
+static long fli_open(flidev_t *dev, char *name, long domain)
+{
+ int retval;
+
+ debug(FLIDEBUG_INFO, "Entering FLIOpen()");
+ debug(FLIDEBUG_INFO, "Trying to open file <%s> in domain %d.",
+ name, domain);
+
+ if ((retval = devalloc(dev)) != 0)
+ {
+ debug(FLIDEBUG_WARN, "error devalloc() %d [%s]",
+ retval, strerror(-retval));
+ return retval;
+ }
+
+ debug(FLIDEBUG_INFO, "Got device index %d", *dev);
+
+ if ((retval = fli_connect(*dev, name, domain)) != 0)
+ {
+ debug(FLIDEBUG_WARN, "fli_connect() error %d [%s]",
+ retval, strerror(-retval));
+ devfree(*dev);
+ return retval;
+ }
+
+ if ((retval = devices[*dev]->fli_open(*dev)) != 0)
+ {
+ debug(FLIDEBUG_WARN, "fli_open() error %d [%s]",
+ retval, strerror(-retval));
+ fli_disconnect(*dev);
+ devfree(*dev);
+ return retval;
+ }
+
+ return retval;
+}
+
+static long fli_close(flidev_t dev)
+{
+ CHKDEVICE(dev);
+ CHKFUNCTION(DEVICE->fli_close);
+
+ DEVICE->fli_close(dev);
+ fli_disconnect(dev);
+ devfree(dev);
+
+ return 0;
+}
+
+static long fli_freelist(char **names)
+{
+ int i;
+
+ if (names == NULL)
+ return 0;
+
+ for (i = 0; names[i] != NULL; i++)
+ xfree(names[i]);
+ xfree(names);
+
+ return 0;
+}
+
+LIBFLIAPI FLIGrabFrame(flidev_t dev, void* buff,
+ size_t buffsize, size_t* bytesgrabbed)
+{
+ dev=dev; buff=buff; buffsize=buffsize;bytesgrabbed=bytesgrabbed;
+ return -EFAULT;
+}
+
+/**
+ Get a handle to an FLI device. This function requires the filename
+ and domain of the requested device. Valid device filenames can be
+ obtained using the \texttt{FLIList()} function. An application may
+ use any number of handles associated with the same physical
+ device. When doing so, it is important to lock the appropriate
+ device to ensure that multiple accesses to the same device do not
+ occur during critical operations.
+
+ @param dev Pointer to where a device handle will be placed.
+
+ @param name Pointer to a string where the device filename to be
+ opened is stored. For parallel port devices that are not probed by
+ \texttt{FLIList()} (Windows 95/98/Me), place the address of the
+ parallel port in a string in ascii form ie: "0x378".
+
+ @param domain Domain to apply to \texttt{name} for device opening.
+ This is a bitwise ORed combination of interface method and device
+ type. Valid interfaces include \texttt{FLIDOMAIN_PARALLEL_PORT},
+ \texttt{FLIDOMAIN_USB}, \texttt{FLIDOMAIN_SERIAL}, and
+ \texttt{FLIDOMAIN_INET}. Valid device types include
+ \texttt{FLIDEVICE_CAMERA}, \texttt{FLIDOMAIN_FILTERWHEEL}, and
+ \texttt{FLIDOMAIN_FOCUSER}.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIList
+ @see FLIClose
+ @see flidomain_t
+*/
+LIBFLIAPI FLIOpen(flidev_t *dev, char *name, flidomain_t domain)
+{
+ return fli_open(dev, name, domain);
+}
+
+/**
+ Enable debugging of API operations and communications. Use this
+ function in combination with FLIDebug to assist in diagnosing
+ problems that may be encountered during programming.
+
+ @param host Name of the file to send debugging information to.
+ This parameter is ignored under Linux where \texttt{syslog(3)} is
+ used to send debug messages (see \texttt{syslog.conf(5)} for how to
+ configure syslogd).
+
+ @param level Debug level. A value of \texttt{FLIDEBUG_NONE} disables
+ debugging. Values of \texttt{FLIDEBUG_FAIL}, \texttt{FLIDEBUG_WARN}, and
+ \texttt{FLIDEBUG_INFO} enable progressively more verbose debug messages.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+*/
+LIBFLIAPI FLISetDebugLevel(char *host, flidebug_t level)
+{
+ setdebuglevel(host, level);
+ return 0;
+}
+
+/**
+ Close a handle to a FLI device.
+
+ @param dev The device handle to be closed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIOpen
+*/
+LIBFLIAPI FLIClose(flidev_t dev)
+{
+ return fli_close(dev);
+}
+
+/**
+ Get the current library version. This function copies up to
+ \texttt{len - 1} characters of the current library version string
+ followed by a terminating \texttt{NULL} character into the buffer
+ pointed to by \texttt{ver}.
+
+ @param ver Pointer to a character buffer where the library version
+ string is to be placed.
+
+ @param len The size in bytes of the buffer pointed to by
+ \texttt{ver}.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+*/
+LIBFLIAPI FLIGetLibVersion(char* ver, size_t len)
+{
+ if (len > 0 && ver == NULL)
+ return -EINVAL;
+
+ if ((size_t) snprintf(ver, len, "%s", version) >= len)
+ return -EOVERFLOW;
+ else
+ return 0;
+}
+
+/**
+ Get the model of a given device. This function copies up to
+ \texttt{len - 1} characters of the model string for device
+ \texttt{dev}, followed by a terminating \texttt{NULL} character
+ into the buffer pointed to by \texttt{model}.
+
+ @param dev Device to find model of.
+
+ @param model Pointer to a character buffer where the model string
+ is to be placed.
+
+ @param len The size in bytes of buffer pointed to by
+ \texttt{model}.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetHWRevision
+ @see FLIGetFWRevision
+ @see FLIGetSerialNum
+*/
+LIBFLIAPI FLIGetModel(flidev_t dev, char* model, size_t len)
+{
+ if (model == NULL)
+ return -EINVAL;
+
+ CHKDEVICE(dev);
+
+ if (DEVICE->devinfo.model == NULL)
+ {
+ model[0] = '\0';
+ return 0;
+ }
+
+ if ((size_t) snprintf(model, len, "%s", DEVICE->devinfo.model) >= len)
+ return -EOVERFLOW;
+ else
+ return 0;
+}
+
+/**
+ Find the dimensions of a pixel in the array of the given device.
+
+ @param dev Device to find the pixel size of.
+
+ @param pixel_x Pointer to a double which will receive the size (in
+ microns) of a pixel in the x direction.
+
+ @param pixel_y Pointer to a double which will receive the size (in
+ microns) of a pixel in the y direction.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetArrayArea
+ @see FLIGetVisibleArea
+*/
+LIBFLIAPI FLIGetPixelSize(flidev_t dev, double *pixel_x, double *pixel_y)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_PIXEL_SIZE, 2,
+ pixel_x, pixel_y);
+}
+
+/**
+ Get the hardware revision of a given device.
+
+ @param dev Device to find the hardware revision of.
+
+ @param hwrev Pointer to a long which will receive the hardware
+ revision.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetModel
+ @see FLIGetFWRevision
+ @see FLIGetSerialNum
+*/
+LIBFLIAPI FLIGetHWRevision(flidev_t dev, long *hwrev)
+{
+ CHKDEVICE(dev);
+
+ *hwrev = DEVICE->devinfo.hwrev;
+ return 0;
+}
+
+/**
+ Get firmware revision of a given device.
+
+ @param dev Device to find the firmware revision of.
+
+ @param fwrev Pointer to a long which will receive the firmware
+ revision.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetModel
+ @see FLIGetHWRevision
+ @see FLIGetSerialNum
+*/
+LIBFLIAPI FLIGetFWRevision(flidev_t dev, long *fwrev)
+{
+ CHKDEVICE(dev);
+
+ *fwrev = DEVICE->devinfo.fwrev;
+ return 0;
+}
+
+/**
+ Get the array area of the given camera. This function finds the
+ \emph{total} area of the CCD array for camera \texttt{dev}. This
+ area is specified in terms of a upper-left point and a lower-right
+ point. The upper-left x-coordinate is placed in \texttt{ul_x}, the
+ upper-left y-coordinate is placed in \texttt{ul_y}, the lower-right
+ x-coordinate is placed in \texttt{lr_x}, and the lower-right
+ y-coordinate is placed in \texttt{lr_y}.
+
+ @param dev Camera to get the array area of.
+
+ @param ul_x Pointer to where the upper-left x-coordinate is to be
+ placed.
+
+ @param ul_y Pointer to where the upper-left y-coordinate is to be
+ placed.
+
+ @param lr_x Pointer to where the lower-right x-coordinate is to be
+ placed.
+
+ @param lr_y Pointer to where the lower-right y-coordinate is to be
+ placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetVisibleArea
+ @see FLISetImageArea
+*/
+LIBFLIAPI FLIGetArrayArea(flidev_t dev, long* ul_x, long* ul_y,
+ long* lr_x, long* lr_y)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_ARRAY_AREA, 4,
+ ul_x, ul_y, lr_x, lr_y);
+}
+
+/**
+ Get the visible area of the given camera. This function finds the
+ \emph{visible} area of the CCD array for the camera \texttt{dev}.
+ This area is specified in terms of a upper-left point and a
+ lower-right point. The upper-left x-coordinate is placed in
+ \texttt{ul_x}, the upper-left y-coordinate is placed in
+ \texttt{ul_y}, the lower-right x-coordinate is placed in
+ \texttt{lr_x}, the lower-right y-coordinate is placed in
+ \texttt{lr_y}.
+
+ @param dev Camera to get the visible area of.
+
+ @param ul_x Pointer to where the upper-left x-coordinate is to be
+ placed.
+
+ @param ul_y Pointer to where the upper-left y-coordinate is to be
+ placed.
+
+ @param lr_x Pointer to where the lower-right x-coordinate is to be
+ placed.
+
+ @param lr_y Pointer to where the lower-right y-coordinate is to be
+ placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetArrayArea
+ @see FLISetImageArea
+*/
+LIBFLIAPI FLIGetVisibleArea(flidev_t dev, long* ul_x, long* ul_y,
+ long* lr_x, long* lr_y)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_VISIBLE_AREA, 4,
+ ul_x, ul_y, lr_x, lr_y);
+}
+
+/**
+ Set the exposure time for a camera. This function sets the
+ exposure time for the camera \texttt{dev} to \texttt{exptime} msec.
+
+ @param dev Camera to set the exposure time of.
+
+ @param exptime Exposure time in msec.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIExposeFrame
+ @see FLICancelExposure
+ @see FLIGetExposureStatus
+*/
+LIBFLIAPI FLISetExposureTime(flidev_t dev, long exptime)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_EXPOSURE_TIME, 1, &exptime);
+}
+
+/**
+ Set the image area for a given camera. This function sets the
+ image area for camera \texttt{dev} to an area specified in terms of
+ a upper-left point and a lower-right point. The upper-left
+ x-coordinate is \texttt{ul_x}, the upper-left y-coordinate is
+ \texttt{ul_y}, the lower-right x-coordinate is \texttt{lr_x}, and
+ the lower-right y-coordinate is \texttt{lr_y}. Note that the given
+ lower-right coordinate must take into account the horizontal and
+ vertical bin factor settings, but the upper-left coordinate is
+ absolute. In other words, the lower-right coordinate used to set
+ the image area is a virtual point $(lr_x', lr_y')$ determined by:
+
+ \[ lr_x' = ul_x + (lr_x - ul_x) / hbin \]
+ \[ lr_y' = ul_y + (lr_y - ul_y) / vbin \]
+
+ Where $(lr_x', lr_y')$ is the coordinate to pass to the
+ \texttt{FLISetImageArea} function, $(ul_x, ul_y)$ and $(lr_x,
+ lr_y)$ are the absolute coordinates of the desired image area,
+ $hbin$ is the horizontal bin factor, and $vbin$ is the vertical bin
+ factor.
+
+ @param dev Camera to set image area of.
+
+ @param ul_x Upper-left x-coordinate of image area.
+
+ @param ul_y Upper-left y-coordinate of image area.
+
+ @param lr_x Lower-right x-coordinate of image area ($lr_x'$ from
+ above).
+
+ @param lr_y Lower-right y-coordinate of image area ($lr_y'$ from
+ above).
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetVisibleArea
+ @see FLIGetArrayArea
+*/
+LIBFLIAPI FLISetImageArea(flidev_t dev, long ul_x, long ul_y,
+ long lr_x, long lr_y)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_IMAGE_AREA, 4,
+ &ul_x, &ul_y, &lr_x, &lr_y);
+}
+
+/**
+ Set the horizontal bin factor for a given camera. This function
+ sets the horizontal bin factor for the camera \texttt{dev} to
+ \texttt{hbin}. The valid range of the \texttt{hbin} parameter is
+ from 1 to 16.
+
+ @param dev Camera to set horizontal bin factor of.
+
+ @param hbin Horizontal bin factor.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLISetVBin
+ @see FLISetImageArea
+*/
+LIBFLIAPI FLISetHBin(flidev_t dev, long hbin)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_HBIN, 1, &hbin);
+}
+
+/**
+ Set the vertical bin factor for a given camera. This function sets
+ the vertical bin factor for the camera \texttt{dev} to
+ \texttt{vbin}. The valid range of the \texttt{vbin} parameter is
+ from 1 to 16.
+
+ @param dev Camera to set vertical bin factor of.
+
+ @param vbin Vertical bin factor.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLISetHBin
+ @see FLISetImageArea
+*/
+LIBFLIAPI FLISetVBin(flidev_t dev, long vbin)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_VBIN, 1, &vbin);
+}
+
+/**
+ Set the frame type for a given camera. This function sets the frame type
+ for camera \texttt{dev} to \texttt{frametype}. The \texttt{frametype}
+ parameter is either \texttt{FLI_FRAME_TYPE_NORMAL} for a normal frame
+ where the shutter opens or \texttt{FLI_FRAME_TYPE_DARK} for a dark frame
+ where the shutter remains closed.
+
+ @param cam Camera to set the frame type of.
+
+ @param frametype Frame type: \texttt{FLI_FRAME_TYPE_NORMAL} or \texttt{FLI_FRAME_TYPE_DARK}.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see fliframe_t
+ @see FLIExposeFrame
+*/
+LIBFLIAPI FLISetFrameType(flidev_t dev, fliframe_t frametype)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_FRAME_TYPE, 1, &frametype);
+}
+
+/**
+ Cancel an exposure for a given camera. This function cancels an
+ exposure in progress by closing the shutter.
+
+ @param dev Camera to cancel the exposure of.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIExposeFrame
+ @see FLIGetExposureStatus
+ @see FLISetExposureTime
+*/
+LIBFLIAPI FLICancelExposure(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_CANCEL_EXPOSURE, 0);
+}
+
+/**
+ Find the remaining exposure time of a given camera. This functions
+ places the remaining exposure time (in milliseconds) in the
+ location pointed to by \texttt{timeleft}.
+
+ @param dev Camera to find the remaining exposure time of.
+
+ @param timeleft Pointer to where the remaining exposure time (in milliseonds) will be placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIExposeFrame
+ @see FLICancelExposure
+ @see FLISetExposureTime
+*/
+LIBFLIAPI FLIGetExposureStatus(flidev_t dev, long *timeleft)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_EXPOSURE_STATUS, 1, timeleft);
+}
+
+/**
+ Set the temperature of a given camera. This function sets the
+ temperature of the CCD camera \texttt{dev} to \texttt{temperature}
+ degrees Celsius. The valid range of the \texttt{temperature}
+ parameter is from -55 C to 45 C.
+
+ @param dev Camera device to set the temperature of.
+
+ @param temperature Temperature in Celsius to set CCD camera cold finger to.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetTemperature
+*/
+LIBFLIAPI FLISetTemperature(flidev_t dev, double temperature)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_TEMPERATURE, 1,
+ &temperature);
+}
+
+/**
+ Get the temperature of a given camera. This function places the
+ temperature of the CCD camera cold finger of device \texttt{dev} in
+ the location pointed to by \texttt{temperature}.
+
+ @param dev Camera device to get the temperature of.
+
+ @param temperature Pointer to where the temperature will be placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLISetTemperature
+*/
+LIBFLIAPI FLIGetTemperature(flidev_t dev, double *temperature)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_TEMPERATURE, 1, temperature);
+}
+
+/**
+ Grab a row of an image. This function grabs the next available row
+ of the image from camera device \texttt{dev}. The row of width
+ \texttt{width} is placed in the buffer pointed to by \texttt{buff}.
+ The size of the buffer pointed to by \texttt{buff} must take into
+ account the bit depth of the image, meaning the buffer size must be
+ at least \texttt{width} bytes for an 8-bit image, and at least
+ 2*\texttt{width} for a 16-bit image.
+
+ @param dev Camera whose image to grab the next available row from.
+
+ @param buff Pointer to where the next available row will be placed.
+
+ @param width Row width in pixels.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGrabFrame
+*/
+LIBFLIAPI FLIGrabRow(flidev_t dev, void *buff, size_t width)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GRAB_ROW, 2, buff, &width);
+}
+
+/**
+ Expose a frame for a given camera. This function exposes a frame
+ according to the settings (image area, exposure time, bit depth,
+ etc.) of camera \texttt{dev}. The settings of \texttt{dev} must be
+ valid for the camera device. They are set by calling the
+ appropriate set library functions. This function returns after the
+ exposure has started.
+
+ @param dev Camera to expose the frame of.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLISetExposureTime
+ @see FLISetFrameType
+ @see FLISetImageArea
+ @see FLISetHBin
+ @see FLISetVBin
+ @see FLISetNFlushes
+ @see FLISetBitDepth
+ @see FLIGrabFrame
+ @see FLICancelExposure
+ @see FLIGetExposureStatus
+*/
+LIBFLIAPI FLIExposeFrame(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_EXPOSE_FRAME, 0);
+}
+
+/**
+ Flush rows of a given camera. This function flushes \texttt{rows}
+ rows of camera \texttt{dev} \texttt{repeat} times.
+
+ @param dev Camera to flush rows of.
+
+ @param rows Number of rows to flush.
+
+ @param repeat Number of times to flush each row.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLISetNFlushes
+*/
+LIBFLIAPI FLIFlushRow(flidev_t dev, long rows, long repeat)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_FLUSH_ROWS, 2, &rows, &repeat);
+}
+
+/**
+ Set the number of flushes for a given camera. This function sets
+ the number of times the CCD array of camera \texttt{dev} is flushed
+ \emph{before} exposing a frame to \texttt{nflushes}. The valid
+ range of the \texttt{nflushes} parameter is from 1 to 16.
+
+ @param dev Camera to set the number of flushes of.
+
+ @param nflushes Number of times to flush CCD array before an
+ exposure.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIFlushRow
+ @see FLIExposeFrame
+*/
+LIBFLIAPI FLISetNFlushes(flidev_t dev, long nflushes)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_FLUSHES, 1, &nflushes);
+}
+
+/**
+ Set the gray-scale bit depth for a given camera. This function
+ sets the gray-scale bit depth of camera \texttt{dev} to
+ \texttt{bitdepth}. The \texttt{bitdepth} parameter is either
+ \texttt{FLI_MODE_8BIT} for 8-bit mode or \texttt{FLI_MODE_16BIT}
+ for 16-bit mode.
+
+ @param dev Camera to set the bit depth of.
+
+ @param bitdepth Gray-scale bit depth: \texttt{FLI_MODE_8BIT} or
+ \texttt{FLI_MODE_16BIT}.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see flibitdepth_t
+ @see FLIExposeFrame
+*/
+LIBFLIAPI FLISetBitDepth(flidev_t dev, flibitdepth_t bitdepth)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_BIT_DEPTH, 1, &bitdepth);
+}
+
+/**
+ Read the I/O port of a given camera. This function reads the I/O
+ port on camera \texttt{dev} and places the value in the location
+ pointed to by \texttt{ioportset}.
+
+ @param dev Camera to read the I/O port of.
+
+ @param ioportset Pointer to where the I/O port data will be stored.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIWriteIOPort
+ @see FLIConfigureIOPort
+*/
+LIBFLIAPI FLIReadIOPort(flidev_t dev, long *ioportset)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_READ_IOPORT, 1, ioportset);
+}
+
+/**
+ Write to the I/O port of a given camera. This function writes the
+ value \texttt{ioportset} to the I/O port on camera \texttt{dev}.
+
+ @param dev Camera to write I/O port of.
+
+ @param ioportset Data to be written to the I/O port.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIReadIOPort
+ @see FLIConfigureIOPort
+*/
+LIBFLIAPI FLIWriteIOPort(flidev_t dev, long ioportset)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_WRITE_IOPORT, 1, &ioportset);
+}
+
+/**
+ Configure the I/O port of a given camera. This function configures
+ the I/O port on camera \texttt{dev} with the value
+ \texttt{ioportset}.
+
+ The I/O configuration of each pin on a given camera is determined by the
+ value of \texttt{ioportset}. Setting a respective I/O bit enables the
+ port bit for output while clearing an I/O bit enables to port bit for
+ input. By default, all I/O ports are configured as inputs.
+
+ @param dev Camera to configure the I/O port of.
+
+ @param ioportset Data to configure the I/O port with.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIReadIOPort
+ @see FLIWriteIOPort
+*/
+LIBFLIAPI FLIConfigureIOPort(flidev_t dev, long ioportset)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_CONFIGURE_IOPORT, 1,
+ &ioportset);
+}
+
+/**
+ Lock a specified device. This function establishes an exclusive
+ lock (mutex) on the given device to prevent access to the device by
+ any other function or process.
+
+ @param dev Device to lock.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIUnlockDevice
+*/
+LIBFLIAPI FLILockDevice(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_lock(dev);
+}
+
+/**
+ Unlock a specified device. This function releases a previously
+ established exclusive lock (mutex) on the given device to allow
+ access to the device by any other function or process.
+
+ @param dev Device to unlock.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLILockDevice
+*/
+LIBFLIAPI FLIUnlockDevice(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_unlock(dev);
+}
+
+/**
+ Control the shutter on a given camera. This function controls the
+ shutter function on camera \texttt{dev} according to the
+ \texttt{shutter} parameter.
+
+ @param dev Device to control the shutter of.
+
+ @param shutter How to control the shutter. A value of
+ \texttt{FLI_SHUTTER_CLOSE} closes the shutter and
+ \texttt{FLI_SHUTTER_OPEN} opens the shutter.
+ \texttt{FLI_SHUTTER_EXTERNAL_TRIGGER_LOW} causes the exposure to begin
+ only when a logic LOW is detected on I/O port bit 0.
+ \texttt{FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH} causes the exposure to begin
+ only when a logic HIGH is detected on I/O port bit 0. This setting
+ may not be available on all cameras.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see flishutter_t
+*/
+LIBFLIAPI FLIControlShutter(flidev_t dev, flishutter_t shutter)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_CONTROL_SHUTTER, 1, &shutter);
+}
+
+/**
+ Enables background flushing of CCD array. This function enables the
+ background flushing of the CCD array camera \texttt{dev} according to the
+ \texttt{bgflush} parameter. Note that this function may not succeed
+ on all FLI products as this feature may not be available.
+
+ @param dev Device to control the background flushing of.
+
+ @param bgflush Enables or disables background flushing. A value of
+ \texttt{FLI_BGFLUSH_START} begins background flushing. It is important to
+ note that background flushing is stopped whenever \texttt{FLIExposeFrame()}
+ or \texttt{FLIControlShutter()} are called. \texttt{FLI_BGFLUSH_STOP} stops all
+ background flush activity.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see flibgflush_t
+*/
+LIBFLIAPI FLIControlBackgroundFlush(flidev_t dev, flibgflush_t bgflush)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_CONTROL_BGFLUSH, 1, &bgflush);
+}
+
+/**
+ List available devices. This function returns a pointer to a NULL
+ terminated list of device names. The pointer should be freed later
+ with \texttt{FLIFreeList()}. Each device name in the returned list
+ includes the filename needed by \texttt{FLIOpen()}, a separating
+ semicolon, followed by the model name or user assigned device name.
+
+ @param domain Domain to list the devices of. This is a bitwise
+ ORed combination of interface method and device type. Valid
+ interfaces include \texttt{FLIDOMAIN_PARALLEL_PORT},
+ \texttt{FLIDOMAIN_USB}, \texttt{FLIDOMAIN_SERIAL}, and
+ \texttt{FLIDOMAIN_INET}. Valid device types include
+ \texttt{FLIDEVICE_CAMERA}, \texttt{FLIDOMAIN_FILTERWHEEL}, and
+ \texttt{FLIDOMAIN_FOCUSER}.
+
+ @param names Pointer to where the device name list will be placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see flidomain_t
+ @see FLIFreeList
+ @see FLIOpen
+*/
+LIBFLIAPI FLIList(flidomain_t domain, char ***names)
+{
+ debug(FLIDEBUG_INFO, "FLIList() domain %04x", domain);
+ return fli_list(domain, names);
+}
+
+/**
+ Free a previously generated device list. Use this function after
+ \texttt{FLIList()} to free the list of device names.
+
+ @param names Pointer to the list.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIList
+*/
+LIBFLIAPI FLIFreeList(char **names)
+{
+ return fli_freelist(names);
+}
+
+/**
+ Set the filter wheel position of a given device. Use this function
+ to set the filter wheel position of \texttt{dev} to
+ \texttt{filter}.
+
+ @param dev Filter wheel device handle.
+
+ @param filter Desired filter wheel position.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetFilterPos
+*/
+LIBFLIAPI FLISetFilterPos(flidev_t dev, long filter)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_FILTER_POS, 1, &filter);
+}
+
+/**
+ Get the filter wheel position of a given device. Use this function
+ to get the filter wheel position of \texttt{dev}.
+
+ @param dev Filter wheel device handle.
+
+ @param filter Pointer to where the filter wheel position will be
+ placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLISetFilterPos
+*/
+LIBFLIAPI FLIGetFilterPos(flidev_t dev, long *filter)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_FILTER_POS, 1, filter);
+}
+
+/**
+ Get the filter wheel filter count of a given device. Use this
+ function to get the filter count of filter wheel \texttt{dev}.
+
+ @param dev Filter wheel device handle.
+
+ @param filter Pointer to where the filter wheel filter count will
+ be placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+*/
+LIBFLIAPI FLIGetFilterCount(flidev_t dev, long *filter)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_FILTER_COUNT, 1, filter);
+}
+
+/**
+ Step the filter wheel or focuser motor of a given device. Use this
+ function to move the focuser or filter wheel \texttt{dev} by an
+ amount \texttt{steps}.
+
+ @param dev Filter wheel or focuser device handle.
+
+ @param steps Number of steps to move the focuser or filter wheel.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetStepperPosition
+*/
+LIBFLIAPI FLIStepMotor(flidev_t dev, long steps)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_STEP_MOTOR, 1, &steps);
+}
+
+/**
+ Get the stepper motor position of a given device. Use this
+ function to read the stepper motor position of filter wheel or
+ focuser \texttt{dev}.
+
+ @param dev Filter wheel or focuser device handle.
+
+ @param position Pointer to where the postion of the stepper motor
+ will be placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIStepMotor
+*/
+LIBFLIAPI FLIGetStepperPosition(flidev_t dev, long *position)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_STEPPER_POS, 1, position);
+}
+
+/**
+ Home a given focuser. Use this function to home focuser
+ \texttt{dev}.
+
+ @param dev Focuser device handle.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+*/
+LIBFLIAPI FLIHomeFocuser(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_HOME_FOCUSER, 0);
+}
+
+/* This stuff is used by the next four functions */
+
+typedef struct list {
+ char *filename;
+ char *name;
+ long domain;
+ struct list *next;
+} list_t;
+
+static list_t *firstdevice = NULL;
+static list_t *currentdevice = NULL;
+
+/**
+ Creates a list of all devices within a specified
+ \texttt{domain}. Use \texttt{FLIDeleteList()} to delete the list
+ created with this function. This function is the first called begin
+ the iteration through the list of current FLI devices attached.
+
+ @param domain Domain to search for devices, set to zero to search all domains.
+ This parameter must contain the device type.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIDeleteList
+ @see FLIListFirst
+ @see FLIListNext
+*/
+LIBFLIAPI FLICreateList(flidomain_t domain)
+{
+ char **list;
+ flidomain_t domord[5];
+ int i, j, k;
+
+ for (i = 0; i < 5; i++)
+ {
+ domord[i] = 0;
+ }
+
+ if (firstdevice != NULL)
+ {
+ FLIDeleteList();
+ }
+ currentdevice = NULL;
+
+ if ((domain & 0x00ff) != 0)
+ {
+ domord[0] = domain;
+ }
+ else
+ {
+ domord[0] = domain | FLIDOMAIN_PARALLEL_PORT;
+ domord[1] = domain | FLIDOMAIN_USB;
+ domord[2] = domain | FLIDOMAIN_SERIAL;
+ }
+
+ i = 0;
+ while (domord[i] != 0)
+ {
+ debug(FLIDEBUG_INFO, "Searching for domain 0x%04x.", domord[i]);
+ FLIList(domord[i], &list);
+ if (list != NULL)
+ {
+ j = 0;
+ while (list[j] != NULL)
+ {
+ if (firstdevice == NULL)
+ {
+ firstdevice = (list_t *)xmalloc(sizeof(list_t));
+ if (firstdevice == NULL)
+ return -ENOMEM;
+ currentdevice = firstdevice;
+ }
+ else
+ {
+ currentdevice->next = (list_t *) xmalloc(sizeof(list_t));
+ if (currentdevice->next == NULL)
+ return -ENOMEM;
+ currentdevice = currentdevice->next;
+ }
+ currentdevice->next = NULL;
+ currentdevice->domain = domord[i];
+ currentdevice->filename = NULL;
+ currentdevice->name = NULL;
+
+ k = 0;
+ while (k < (int) strlen(list[j]))
+ {
+ if (list[j][k] == ';')
+ {
+ currentdevice->filename = (char *) xmalloc(k+1);
+ if (currentdevice->filename != NULL)
+ {
+ strncpy(currentdevice->filename, list[j], k);
+ currentdevice->filename[k] = '\0';
+ }
+ currentdevice->name = (char *) xmalloc(strlen(&list[j][k+1]) + 1);
+ if (currentdevice->name != NULL)
+ {
+ strcpy(currentdevice->name, &list[j][k+1]);
+ }
+ break;
+ }
+ k++;
+ }
+ j++;
+ }
+ FLIFreeList(list);
+ }
+ i++;
+ }
+ return 0;
+}
+
+/**
+ Deletes a list of devices created by \texttt{FLICreateList()}.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLICreateList
+ @see FLIListFirst
+ @see FLIListNext
+*/
+LIBFLIAPI FLIDeleteList(void)
+{
+ list_t *dev = firstdevice;
+ list_t *last;
+
+ while (dev != NULL)
+ {
+ if (dev->filename != NULL)
+ xfree(dev->filename);
+ if (dev->name != NULL)
+ xfree(dev->name);
+ last = dev;
+ dev = dev->next;
+ xfree(last);
+ }
+
+ firstdevice = NULL;
+ currentdevice = NULL;
+
+ return 0;
+}
+
+/**
+ Obtains the first device in the list. Use this function to
+ get the first \texttt{domain}, \texttt{filename} and \texttt{name}
+ from the list of attached FLI devices created using
+ the function \texttt{FLICreateList()}. Use
+ \texttt{FLIListNext()} to obtain more found devices.
+
+ @param domain Pointer to where to domain of the device will be placed.
+
+ @param filename Pointer to where the filename of the device will be placed.
+
+ @param fnlen Length of the supplied buffer to hold the filename.
+
+ @param name Pointer to where the name of the device will be placed.
+
+ @param namelen Length of the supplied buffer to hold the name.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLICreateList
+ @see FLIDeleteList
+ @see FLIListNext
+*/
+LIBFLIAPI FLIListFirst(flidomain_t *domain, char *filename,
+ size_t fnlen, char *name, size_t namelen)
+{
+ currentdevice = firstdevice;
+ return FLIListNext(domain, filename, fnlen, name, namelen);
+}
+
+/**
+ Obtains the next device in the list. Use this function to
+ get the next \texttt{domain}, \texttt{filename} and \texttt{name}
+ from the list of attached FLI devices created using
+ the function \texttt{FLICreateList()}.
+
+ @param domain Pointer to where to domain of the device will be placed.
+
+ @param filename Pointer to where the filename of the device will be placed.
+
+ @param fnlen Length of the supplied buffer to hold the filename.
+
+ @param name Pointer to where the name of the device will be placed.
+
+ @param namelen Length of the supplied buffer to hold the name.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLICreateList
+ @see FLIDeleteList
+ @see FLIListFirst
+*/
+LIBFLIAPI FLIListNext(flidomain_t *domain, char *filename,
+ size_t fnlen, char *name, size_t namelen)
+{
+ if (currentdevice == NULL)
+ {
+ *domain = 0;
+ filename[0] = '\0';
+ name[0] = '\0';
+ return -EBADF;
+ }
+
+ *domain = currentdevice->domain;
+ strncpy(filename, currentdevice->filename, fnlen);
+ filename[fnlen-1] = '\0';
+ strncpy(name, currentdevice->name, namelen);
+ name[namelen-1] = '\0';
+
+ currentdevice = currentdevice->next;
+ return 0;
+}
diff --git a/kstars/kstars/indi/fli/libfli.h b/kstars/kstars/indi/fli/libfli.h
new file mode 100644
index 00000000..351a9e8e
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli.h
@@ -0,0 +1,214 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_H_
+#define _LIBFLI_H_
+
+#include <sys/types.h>
+
+/**
+ An opaque handle used by library functions to refer to FLI
+ hardware.
+*/
+typedef long flidev_t;
+
+/**
+ The domain of an FLI device. This consists of a bitwise ORed
+ combination of interface method and device type. Valid interfaces
+ are \texttt{FLIDOMAIN_PARALLEL_PORT}, \texttt{FLIDOMAIN_USB},
+ \texttt{FLIDOMAIN_SERIAL}, and \texttt{FLIDOMAIN_INET}. Valid
+ device types are \texttt{FLIDEVICE_CAMERA},
+ \texttt{FLIDOMAIN_FILTERWHEEL}, and \texttt{FLIDOMAIN_FOCUSER}.
+
+ @see FLIOpen
+ @see FLIList
+ */
+typedef long flidomain_t;
+
+#define FLIDOMAIN_NONE (0x00)
+#define FLIDOMAIN_PARALLEL_PORT (0x01)
+#define FLIDOMAIN_USB (0x02)
+#define FLIDOMAIN_SERIAL (0x03)
+#define FLIDOMAIN_INET (0x04)
+
+#define FLIDEVICE_NONE (0x000)
+#define FLIDEVICE_CAMERA (0x100)
+#define FLIDEVICE_FILTERWHEEL (0x200)
+#define FLIDEVICE_FOCUSER (0x300)
+
+/**
+ The frame type for an FLI CCD camera device. Valid frame types are
+ \texttt{FLI_FRAME_TYPE_NORMAL} and \texttt{FLI_FRAME_TYPE_DARK}.
+
+ @see FLISetFrameType
+*/
+typedef long fliframe_t;
+
+#define FLI_FRAME_TYPE_NORMAL (0)
+#define FLI_FRAME_TYPE_DARK (1)
+
+/**
+ The gray-scale bit depth for an FLI camera device. Valid bit
+ depths are \texttt{FLI_MODE_8BIT} and \texttt{FLI_MODE_16BIT}.
+
+ @see FLISetBitDepth
+*/
+typedef long flibitdepth_t;
+
+#define FLI_MODE_8BIT (0)
+#define FLI_MODE_16BIT (1)
+
+/**
+ Type used for shutter operations for an FLI camera device. Valid
+ shutter types are \texttt{FLI_SHUTTER_CLOSE},
+ \texttt{FLI_SHUTTER_OPEN},
+ \texttt{FLI_SHUTTER_EXTERNAL_TRIGGER},
+ \texttt{FLI_SHUTTER_EXTERNAL_TRIGGER_LOW}, and
+ \texttt{FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH}.
+
+ @see FLIControlShutter
+*/
+typedef long flishutter_t;
+
+#define FLI_SHUTTER_CLOSE (0x0000)
+#define FLI_SHUTTER_OPEN (0x0001)
+#define FLI_SHUTTER_EXTERNAL_TRIGGER (0x0002)
+#define FLI_SHUTTER_EXTERNAL_TRIGGER_LOW (0x0002)
+#define FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH (0x0004)
+
+/**
+ Type used for background flush operations for an FLI camera device. Valid
+ bgflush types are \texttt{FLI_BGFLUSH_STOP} and
+ \texttt{FLI_BGFLUSH_START}.
+
+ @see FLIControlBackgroundFlush
+*/
+typedef long flibgflush_t;
+
+#define FLI_BGFLUSH_STOP (0x0000)
+#define FLI_BGFLUSH_START (0x0001)
+
+/**
+ Type specifying library debug levels. Valid debug levels are
+ \texttt{FLIDEBUG_NONE}, \texttt{FLIDEBUG_INFO},
+ \texttt{FLIDEBUG_WARN}, and \texttt{FLIDEBUG_FAIL}.
+
+ @see FLISetDebugLevel
+*/
+typedef long flidebug_t;
+
+#define FLIDEBUG_NONE (0x00)
+#define FLIDEBUG_INFO (0x01)
+#define FLIDEBUG_WARN (0x02)
+#define FLIDEBUG_FAIL (0x04)
+#define FLIDEBUG_ALL (FLIDEBUG_INFO | FLIDEBUG_WARN | FLIDEBUG_FAIL)
+
+#ifdef WIN32
+#ifndef LIBFLIAPI
+#define LIBFLIAPI __declspec(dllimport) long __stdcall
+#endif
+#else
+#define LIBFLIAPI long
+#endif
+
+/* Library API Function prototypes */
+
+#ifdef __cplusplus
+extern "C" { // only need to export C interface if used by C++ source code
+#endif
+
+LIBFLIAPI FLIOpen(flidev_t *dev, char *name, flidomain_t domain);
+LIBFLIAPI FLISetDebugLevel(char *host, flidebug_t level);
+LIBFLIAPI FLIClose(flidev_t dev);
+LIBFLIAPI FLIGetLibVersion(char* ver, size_t len);
+LIBFLIAPI FLIGetModel(flidev_t dev, char* model, size_t len);
+LIBFLIAPI FLIGetPixelSize(flidev_t dev, double *pixel_x, double *pixel_y);
+LIBFLIAPI FLIGetHWRevision(flidev_t dev, long *hwrev);
+LIBFLIAPI FLIGetFWRevision(flidev_t dev, long *fwrev);
+LIBFLIAPI FLIGetArrayArea(flidev_t dev, long* ul_x, long* ul_y,
+ long* lr_x, long* lr_y);
+LIBFLIAPI FLIGetVisibleArea(flidev_t dev, long* ul_x, long* ul_y,
+ long* lr_x, long* lr_y);
+LIBFLIAPI FLISetExposureTime(flidev_t dev, long exptime);
+LIBFLIAPI FLISetImageArea(flidev_t dev, long ul_x, long ul_y,
+ long lr_x, long lr_y);
+LIBFLIAPI FLISetHBin(flidev_t dev, long hbin);
+LIBFLIAPI FLISetVBin(flidev_t dev, long vbin);
+LIBFLIAPI FLISetFrameType(flidev_t dev, fliframe_t frametype);
+LIBFLIAPI FLICancelExposure(flidev_t dev);
+LIBFLIAPI FLIGetExposureStatus(flidev_t dev, long *timeleft);
+LIBFLIAPI FLISetTemperature(flidev_t dev, double temperature);
+LIBFLIAPI FLIGetTemperature(flidev_t dev, double *temperature);
+LIBFLIAPI FLIGrabRow(flidev_t dev, void *buff, size_t width);
+LIBFLIAPI FLIExposeFrame(flidev_t dev);
+LIBFLIAPI FLIFlushRow(flidev_t dev, long rows, long repeat);
+LIBFLIAPI FLISetNFlushes(flidev_t dev, long nflushes);
+LIBFLIAPI FLISetBitDepth(flidev_t dev, flibitdepth_t bitdepth);
+LIBFLIAPI FLIReadIOPort(flidev_t dev, long *ioportset);
+LIBFLIAPI FLIWriteIOPort(flidev_t dev, long ioportset);
+LIBFLIAPI FLIConfigureIOPort(flidev_t dev, long ioportset);
+LIBFLIAPI FLILockDevice(flidev_t dev);
+LIBFLIAPI FLIUnlockDevice(flidev_t dev);
+LIBFLIAPI FLIControlShutter(flidev_t dev, flishutter_t shutter);
+LIBFLIAPI FLIControlBackgroundFlush(flidev_t dev, flibgflush_t bgflush);
+LIBFLIAPI FLIList(flidomain_t domain, char ***names);
+LIBFLIAPI FLIFreeList(char **names);
+LIBFLIAPI FLISetFilterPos(flidev_t dev, long filter);
+LIBFLIAPI FLIGetFilterPos(flidev_t dev, long *filter);
+LIBFLIAPI FLIGetFilterCount(flidev_t dev, long *filter);
+LIBFLIAPI FLIStepMotor(flidev_t dev, long steps);
+LIBFLIAPI FLIGetStepperPosition(flidev_t dev, long *position);
+LIBFLIAPI FLIHomeFocuser(flidev_t dev);
+LIBFLIAPI FLICreateList(flidomain_t domain);
+LIBFLIAPI FLIDeleteList(void);
+LIBFLIAPI FLIListFirst(flidomain_t *domain, char *filename,
+ size_t fnlen, char *name, size_t namelen);
+LIBFLIAPI FLIListNext(flidomain_t *domain, char *filename,
+ size_t fnlen, char *name, size_t namelen);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBFLI_H_ */
diff --git a/kstars/kstars/indi/fli/libfli.pdf b/kstars/kstars/indi/fli/libfli.pdf
new file mode 100644
index 00000000..f5fb45f5
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli.pdf
Binary files differ
diff --git a/kstars/kstars/indi/fli/readme.txt b/kstars/kstars/indi/fli/readme.txt
new file mode 100644
index 00000000..1f3b8925
--- /dev/null
+++ b/kstars/kstars/indi/fli/readme.txt
@@ -0,0 +1,15 @@
+Current Version 1.11
+
+Changes since 1.1
+ - Corrected documentation for function FLIConfigureIOPort()
+ - Added some bounds checking on FLISetImageArea()
+ Note that on cameras with a FWRev < 0x0300 exceeding the set image
+ area will lead to VERY SLOW grabs
+ - Added some bounds checking on FLIGrabRow()
+ - Removed function FLIGrabFrame(), it was never supported anyways
+ - Added FLI_SHUTTER_EXTERNAL_TRIGGER to documentation for FLIControlShutter()
+ - Added FLI_SHUTTER_EXTERNAL_TRIGGER_LOW and FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH
+ - Added FLIStartBackgroundFlush()
+ - Repaired temperature settungs under Linux
+ - Made temperature conversion more portable
+