moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kstars / kstars / indi / fli / libfli-sys.c
blobdda7462f2b3c8c6b1cd5bf2d67aa38b0d98dae2c
1 /*
3 Copyright (c) 2002 Finger Lakes Instrumentation (FLI), L.L.C.
4 All rights reserved.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
10 Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
13 Redistributions in binary form must reproduce the above
14 copyright notice, this list of conditions and the following
15 disclaimer in the documentation and/or other materials
16 provided with the distribution.
18 Neither the name of Finger Lakes Instrumentation (FLI), LLC
19 nor the names of its contributors may be used to endorse or
20 promote products derived from this software without specific
21 prior written permission.
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 POSSIBILITY OF SUCH DAMAGE.
36 ======================================================================
38 Finger Lakes Instrumentation, L.L.C. (FLI)
39 web: http://www.fli-cam.com
40 email: support@fli-cam.com
44 #include <sys/file.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
48 #include <stdio.h>
49 #include <errno.h>
50 #include <string.h>
51 #include <fcntl.h>
52 #include <unistd.h>
53 #include <signal.h>
54 #include <stdlib.h>
55 #include <glob.h>
57 #include "libfli-libfli.h"
58 #include "libfli-debug.h"
59 #include "libfli-mem.h"
60 #include "libfli-camera.h"
61 #include "libfli-filter-focuser.h"
62 #include "libfli-sys.h"
63 #include "libfli-parport.h"
64 #include "libfli-usb.h"
65 #include "libfli-serial.h"
67 #ifndef MIN
68 #define MIN(a, b) ((a) < (b) ? (a) : (b))
69 #endif
71 static long unix_fli_list_parport(flidomain_t domain, char ***names);
72 static long unix_fli_list_usb(flidomain_t domain, char ***names);
73 static long unix_fli_list_serial(flidomain_t domain, char ***names);
75 #ifdef __linux__
76 long linux_usb_reset(flidev_t dev);
77 #endif
79 long unix_fli_connect(flidev_t dev, char *name, long domain)
81 fli_unixio_t *io;
83 CHKDEVICE(dev);
85 if (name == NULL)
86 return -EINVAL;
88 /* Lock functions should be set before any other functions used */
89 DEVICE->fli_lock = unix_fli_lock;
90 DEVICE->fli_unlock = unix_fli_unlock;
92 DEVICE->domain = domain & 0x00ff;
93 DEVICE->devinfo.type = domain & 0xff00;
95 debug(FLIDEBUG_INFO, "Domain: 0x%04x", DEVICE->domain);
96 debug(FLIDEBUG_INFO, " Type: 0x%04x", DEVICE->devinfo.type);
98 if ((io = xcalloc(1, sizeof(fli_unixio_t))) == NULL)
99 return -ENOMEM;
101 if ((io->fd = open(name, O_RDWR)) == -1)
103 xfree(io);
104 return -errno;
107 switch (DEVICE->domain)
109 case FLIDOMAIN_PARALLEL_PORT:
110 DEVICE->fli_io = unix_parportio;
111 break;
113 case FLIDOMAIN_USB:
115 int r;
117 if( (r = unix_usbverifydescriptor(dev, io)) != 0)
119 close(io->fd);
120 xfree(io);
121 return r;
123 DEVICE->fli_io = unix_usbio;
125 break;
127 case FLIDOMAIN_SERIAL:
128 DEVICE->fli_io = unix_serialio;
129 break;
131 default:
132 close(io->fd);
133 xfree(io);
134 return -EINVAL;
137 switch (DEVICE->devinfo.type)
139 case FLIDEVICE_CAMERA:
140 DEVICE->fli_open = fli_camera_open;
141 DEVICE->fli_close = fli_camera_close;
142 DEVICE->fli_command = fli_camera_command;
143 break;
145 case FLIDEVICE_FOCUSER:
146 DEVICE->fli_open = fli_focuser_open;
147 DEVICE->fli_close = fli_focuser_close;
148 DEVICE->fli_command = fli_focuser_command;
149 break;
151 case FLIDEVICE_FILTERWHEEL:
152 DEVICE->fli_open = fli_filter_open;
153 DEVICE->fli_close = fli_filter_close;
154 DEVICE->fli_command = fli_filter_command;
155 break;
157 default:
158 close(io->fd);
159 xfree(io);
160 return -EINVAL;
163 DEVICE->io_data = io;
164 DEVICE->name = xstrdup(name);
165 DEVICE->io_timeout = 60 * 1000; /* 1 min. */
167 return 0;
170 long unix_fli_disconnect(flidev_t dev)
172 int err = 0;
173 fli_unixio_t *io;
175 CHKDEVICE(dev);
177 #ifdef __linux__
178 if ((DEVICE->domain & 0x00ff) == FLIDOMAIN_USB) {
179 debug(FLIDEBUG_INFO, "Resetting device");
180 linux_usb_reset(dev);
182 #endif
184 if ((io = DEVICE->io_data) == NULL)
185 return -EINVAL;
187 if (close(io->fd))
188 err = -errno;
190 xfree(DEVICE->io_data);
192 DEVICE->io_data = NULL;
193 DEVICE->fli_lock = NULL;
194 DEVICE->fli_unlock = NULL;
195 DEVICE->fli_io = NULL;
196 DEVICE->fli_open = NULL;
197 DEVICE->fli_close = NULL;
198 DEVICE->fli_command = NULL;
200 return err;
203 #if defined(_USE_FLOCK_)
205 long unix_fli_lock(flidev_t dev)
207 fli_unixio_t *io = DEVICE->io_data;
209 if (io == NULL)
210 return -ENODEV;
212 if (flock(io->fd, LOCK_EX) == -1)
213 return -errno;
214 else
215 return 0;
218 long unix_fli_unlock(flidev_t dev)
220 fli_unixio_t *io = DEVICE->io_data;
222 if (io == NULL)
223 return -ENODEV;
225 if (flock(io->fd, LOCK_UN) == -1)
226 return -errno;
227 else
228 return 0;
231 #else /* !defined(_USE_FLOCK_) */
233 #define PUBLIC_DIR "/var/spool/uucppublic"
235 long unix_fli_lock(flidev_t dev)
237 int fd, err = 0, locked = 0, i;
238 char tmpf[] = PUBLIC_DIR "/temp.XXXXXX", lockf[PATH_MAX], name[PATH_MAX];
239 FILE *f;
240 unsigned int backoff = 10000;
241 pid_t pid;
243 if ((fd = mkstemp(tmpf)) == -1)
244 return -errno;
246 if ((f = fdopen(fd, "w")) == NULL)
248 err = -errno;
249 goto done;
252 fprintf(f, "%d\n", getpid());
253 fclose(f);
255 if (chmod(tmpf, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
256 S_IROTH | S_IWOTH) == -1)
258 err = -errno;
259 goto done;
262 for (i = 0; DEVICE->name[i] != '\0' && i < PATH_MAX; i++)
263 name[i] = (DEVICE->name[i] == '/') ? '-' : DEVICE->name[i];
265 name[MIN(i, PATH_MAX - 1)] = '\0';
267 if (snprintf(lockf, PATH_MAX, PUBLIC_DIR "/libfli%s.lock",
268 name) >= PATH_MAX)
270 err = -EOVERFLOW;
271 goto done;
274 do {
275 if (link(tmpf, lockf) == -1)
277 int r;
279 if (errno != EEXIST)
281 err = -errno;
282 goto done;
285 if ((f = fopen(lockf, "r")) == NULL)
286 continue;
288 r = fscanf(f, "%d\n", &pid);
289 fclose(f);
290 if (r != 1)
291 continue;
293 if (kill(pid, 0))
295 if (errno == ESRCH)
297 debug(FLIDEBUG_WARN, "Removing stale lock file");
298 unlink(lockf);
301 continue;
303 else
305 usleep(backoff);
306 if ((backoff <<= 2) == 0)
308 err = -ETIMEDOUT;
309 goto done;
313 else
314 locked = 1;
315 } while (!locked);
317 done:
319 unlink(tmpf);
321 return err;
324 long unix_fli_unlock(flidev_t dev)
326 char lockf[PATH_MAX], name[PATH_MAX];
327 FILE *f;
328 pid_t pid = -1;
329 int i;
331 for (i = 0; DEVICE->name[i] != '\0' && i < PATH_MAX; i++)
332 name[i] = (DEVICE->name[i] == '/') ? '-' : DEVICE->name[i];
334 name[MIN(i, PATH_MAX - 1)] = '\0';
336 if (snprintf(lockf, PATH_MAX, PUBLIC_DIR "/libfli%s.lock",
337 name) >= PATH_MAX)
338 return -EOVERFLOW;
340 if ((f = fopen(lockf, "r")) == NULL)
342 debug(FLIDEBUG_WARN, "Trying to unlock `%s' when not locked",
343 DEVICE->name);
344 return -errno;
347 if (fscanf(f, "%d\n", &pid) != 1)
348 debug(FLIDEBUG_WARN, "Invalid lock file for `%s'", DEVICE->name);
350 fclose(f);
352 if (pid != -1 && pid != getpid())
353 debug(FLIDEBUG_WARN, "Forcing unlock of `%s' from process %d",
354 DEVICE->name, pid);
356 unlink(lockf);
358 return 0;
361 #undef PUBLIC_DIR
363 #endif /* defined(_USE_FLOCK_) */
365 long unix_fli_list(flidomain_t domain, char ***names)
367 *names = NULL;
369 switch (domain & 0x00ff)
371 case FLIDOMAIN_PARALLEL_PORT:
372 return unix_fli_list_parport(domain, names);
373 break;
375 case FLIDOMAIN_USB:
376 return unix_fli_list_usb(domain, names);
377 break;
379 case FLIDOMAIN_SERIAL:
380 return unix_fli_list_serial(domain, names);
381 break;
383 default:
384 return -EINVAL;
387 /* Not reached */
388 return -EINVAL;
391 static long unix_fli_list_glob(char *pattern, flidomain_t domain,
392 char ***names)
394 int retval, i, found = 0;
395 char **list;
396 glob_t g;
398 if ((retval = glob(pattern, 0, NULL, &g)))
400 #ifdef GLOB_NOMATCH
401 if (retval != GLOB_NOMATCH)
403 globfree(&g);
404 return -errno;
407 /* retval == GLOB_NOMATCH */
408 g.gl_pathc = 0;
409 #else
410 globfree(&g);
411 return -errno;
412 #endif
415 if ((list = xmalloc((g.gl_pathc + 1) * sizeof(char *))) == NULL)
417 globfree(&g);
418 return -ENOMEM;
421 for (i = 0; i < (int) g.gl_pathc; i++)
423 flidev_t dev;
425 if (FLIOpen(&dev, g.gl_pathv[i], domain))
426 continue;
428 if ((list[found] = xmalloc(strlen(g.gl_pathv[i]) +
429 strlen(DEVICE->devinfo.model) + 2)) == NULL)
431 int j;
433 FLIClose(dev);
434 for (j = 0; j < found; j++)
435 xfree(list[j]);
436 xfree(list);
437 globfree(&g);
438 return -ENOMEM;
441 sprintf(list[found], "%s;%s", g.gl_pathv[i], DEVICE->devinfo.model);
442 FLIClose(dev);
443 found++;
446 globfree(&g);
448 /* Terminate the list */
449 list[found++] = NULL;
451 list = xrealloc(list, found * sizeof(char *));
452 *names = list;
454 return 0;
457 #ifdef __linux__
459 static long unix_fli_list_parport(flidomain_t domain, char ***names)
461 return unix_fli_list_glob(PARPORT_GLOB, domain, names);
464 #else
466 static long unix_fli_list_parport(flidomain_t domain, char ***names)
468 return -EINVAL;
471 #endif
473 static long unix_fli_list_usb(flidomain_t domain, char ***names)
475 return unix_fli_list_glob(USB_GLOB, domain, names);
478 static long unix_fli_list_serial(flidomain_t domain, char ***names)
480 return unix_fli_list_glob(SERIAL_GLOB, domain, names);