Remove generated files
[framework/connectivity/libgphoto2.git] / libgphoto2_port / serial / unix.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * Copyright © 2001 Lutz Müller <lutz@users.sf.net>
4  * Copyright © 2000 Philippe Marzouk <pmarzouk@bigfoot.com>
5  * Copyright © 2000 Edouard Lafargue <Edouard.Lafargue@bigfoot.com>
6  * Copyright © 1999 Johannes Erdfelt <johannes@erdfelt.com>
7  * Copyright © 1999 Scott Fritzinger <scottf@unr.edu>
8  *
9  * Based on work by:
10  * Copyright © 1999 Beat Christen <spiff@longstreet.ch>
11  *      for the toshiba gPhoto library.
12  *                   
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Lesser General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful, 
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Lesser General Public License for more details. 
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27  * Boston, MA 02111-1307, USA.
28  */
29
30 #include "config.h"
31 #include <gphoto2/gphoto2-port-library.h>
32
33 /* Solaris needs this */
34 #define __EXTENSIONS__
35
36 #include <stdlib.h>
37 #include <stdio.h>
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
41 #ifdef HAVE_FCNTL_H
42 #include <fcntl.h>
43 #endif
44 #ifdef HAVE_ERRNO_H
45 #include <errno.h>
46 #endif
47 #include <string.h>
48 #include <signal.h>
49 #include <sys/stat.h>
50 #include <sys/types.h>
51 #ifdef HAVE_SYS_TIME_H
52 #include <sys/time.h>
53 #endif
54 #ifdef HAVE_SYS_IOCTL_H
55 #include <sys/ioctl.h>
56 #endif
57 #ifdef HAVE_SYS_SELECT_H
58 # include <sys/select.h>
59 #endif
60
61 #ifdef HAVE_TERMIOS_H
62 #  include <termios.h>
63 #  ifndef CRTSCTS
64 #    define CRTSCTS  020000000000
65 #  endif
66 #else
67 #  include <sgtty.h>
68 #endif
69
70 #ifdef HAVE_RESMGR
71 #  include <resmgr.h>
72 #endif
73
74 #ifdef HAVE_BAUDBOY
75 #  include <baudboy.h>
76 #elif defined(HAVE_TTYLOCK)
77 #  include <ttylock.h>
78 #elif defined(HAVE_LOCKDEV)
79 #  include <lockdev.h>
80 #endif
81
82 #include <gphoto2/gphoto2-port-result.h>
83 #include <gphoto2/gphoto2-port-log.h>
84 #include <gphoto2/gphoto2-port.h>
85
86 #ifdef ENABLE_NLS
87 #  include <libintl.h>
88 #  undef _
89 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
90 #  ifdef gettext_noop
91 #    define N_(String) gettext_noop (String)
92 #  else
93 #    define N_(String) (String)
94 #  endif 
95 #else
96 #  define textdomain(String) (String)
97 #  define gettext(String) (String)
98 #  define dgettext(Domain,Message) (Message)
99 #  define dcgettext(Domain,Message,Type) (Message)
100 #  define bindtextdomain(Domain,Directory) (Domain)
101 #  define _(String) (String)
102 #  define N_(String) (String)
103 #endif
104
105 #define CHECK(result) {int r=(result); if (r<0) return (r);}
106
107 /* Linux */
108 #ifdef __linux__
109 /* devfs is accounted for in the implementation */
110 #define GP_PORT_SERIAL_PREFIX   "/dev/ttyS%i"
111 #define GP_PORT_SERIAL_RANGE_LOW        0
112 #define GP_PORT_SERIAL_RANGE_HIGH       32
113
114 #ifndef IXANY
115 #define IXANY  0004000
116 #endif
117
118 #endif
119
120 /* FreeBSD */
121 #ifdef __FreeBSD__
122 #if __FreeBSD_version < 600000
123 #define GP_PORT_SERIAL_PREFIX   "/dev/cuaa%x"
124 #else
125 #define GP_PORT_SERIAL_PREFIX   "/dev/cuad%x"
126 #endif
127 #define GP_PORT_SERIAL_RANGE_LOW        0
128 #define GP_PORT_SERIAL_RANGE_HIGH       (0xf)
129 #endif
130
131 /* OpenBSD */
132 /* devices appear to go up to /dev/cuac7, but we just list the first 4 */
133 #ifdef __OpenBSD__
134 # define GP_PORT_SERIAL_PREFIX   "/dev/cua%02x"
135 # define GP_PORT_SERIAL_RANGE_LOW        0
136 # define GP_PORT_SERIAL_RANGE_HIGH       3
137 #endif
138
139 /* NetBSD */
140 #ifdef __NetBSD__
141 #define GP_PORT_SERIAL_PREFIX   "/dev/tty0%i"
142 #define GP_PORT_SERIAL_RANGE_LOW        0
143 #define GP_PORT_SERIAL_RANGE_HIGH       32
144 #endif
145
146 /* Tru64 UNIX */
147 #ifdef __osf__
148 #define GP_PORT_SERIAL_PREFIX   "/dev/tty%02i"
149 #define GP_PORT_SERIAL_RANGE_LOW        0
150 #define GP_PORT_SERIAL_RANGE_HIGH       4
151 #endif
152
153 /* Darwin */
154 #ifdef __APPLE__
155 /* This is the Keyspan USB serial adapter device (UNTESTED) */
156 #define GP_PORT_SERIAL_PREFIX   "/dev/tty.KeyUSA28X%i"
157 #define GP_PORT_SERIAL_RANGE_LOW        111
158 #define GP_PORT_SERIAL_RANGE_HIGH       1112
159 #endif
160
161 /* Solaris */
162 #ifdef sun
163 #define GP_PORT_SERIAL_PREFIX "/dev/tty%c"
164 #define GP_PORT_SERIAL_RANGE_LOW        'a'
165 #define GP_PORT_SERIAL_RANGE_HIGH       'z'
166 #endif
167
168 /* BeOS */
169 #ifdef beos
170 /* ????????????? */
171 #define GP_PORT_SERIAL_PREFIX NULL
172 #define GP_PORT_SERIAL_RANGE_LOW        0
173 #define GP_PORT_SERIAL_RANGE_HIGH       0
174 #endif
175
176 /* Windows */
177 #ifdef WIN32
178 #define GP_PORT_SERIAL_PREFIX   "COM%i:"
179 #define GP_PORT_SERIAL_RANGE_LOW        1
180 #define GP_PORT_SERIAL_RANGE_HIGH       4
181 #endif
182
183 #ifdef OS2
184 #define GP_PORT_SERIAL_PREFIX   "COM%i"
185 #define GP_PORT_SERIAL_RANGE_LOW   1
186 #define GP_PORT_SERIAL_RANGE_HIGH  4
187 #endif
188
189 /* IRIX */
190 #if defined(__sgi)
191 #define GP_PORT_SERIAL_PREFIX "/dev/ttyd%i"
192 #define GP_PORT_SERIAL_RANGE_LOW       1 
193 #define GP_PORT_SERIAL_RANGE_HIGH     11
194 #endif
195
196 /* Others? */
197
198 /* Default */
199 #ifndef GP_PORT_SERIAL_PREFIX
200 #define GP_PORT_SERIAL_PREFIX   "/dev/cua%i"
201 #define GP_PORT_SERIAL_RANGE_LOW        0
202 #define GP_PORT_SERIAL_RANGE_HIGH       0
203 #endif
204
205 #define GP_MODULE "serial"
206
207 struct _GPPortPrivateLibrary {
208         int fd;       /* Device handle */
209         int baudrate; /* Current speed */
210 };
211
212 static int gp_port_serial_check_speed (GPPort *dev);
213
214 GPPortType
215 gp_port_library_type () 
216 {
217         return (GP_PORT_SERIAL);
218 }
219
220 static int
221 gp_port_serial_lock (GPPort *dev, const char *path)
222 {
223 #if defined(HAVE_LOCKDEV)
224         int pid;
225 #endif
226
227         gp_log (GP_LOG_DEBUG, "gphoto2-port-serial",
228                 "Trying to lock '%s'...", path);
229
230 #ifdef HAVE_RESMGR
231         if (!rsm_lock_device(path)) {
232                 return GP_OK;
233         }
234         /* fallthrough */
235 #define __HAVE_LOCKING  
236 #endif
237
238 #if defined(HAVE_TTYLOCK) || defined(HAVE_BAUDBOY)
239         if (ttylock ((char*) path)) {
240                 if (dev)
241                         gp_port_set_error (dev, _("Could not lock device "
242                                                   "'%s'"), path);
243                 return (GP_ERROR_IO_LOCK);
244         }
245 #define __HAVE_LOCKING  
246 #elif defined(HAVE_LOCKDEV)
247         pid = dev_lock (path);
248         if (pid) {
249                 if (dev) {
250                         if (pid > 0)
251                                 gp_port_set_error (dev, _("Device '%s' is "
252                                         "locked by pid %d"), path, pid);
253                         else
254                                 gp_port_set_error (dev, _("Device '%s' could "
255                                         "not be locked (dev_lock returned "
256                                         "%d)"), path, pid);
257                 }
258                 return (GP_ERROR_IO_LOCK);
259         }
260 #define __HAVE_LOCKING  
261 #endif
262
263 #ifndef __HAVE_LOCKING
264 # ifdef __GCC__
265 #  warning No locking library found. 
266 #  warning You will run into problems if you use
267 #  warning gphoto2 with a serial (RS232) camera in 
268 #  warning combination with Konqueror (KDE) or Nautilus (GNOME).
269 #  warning This will *not* concern USB cameras.
270 # endif
271 #endif
272
273         return (GP_OK);
274 }
275
276 static int
277 gp_port_serial_unlock (GPPort *dev, const char *path)
278 {
279 #ifdef HAVE_RESMGR
280         if (!rsm_unlock_device(path))
281                 return GP_OK;
282         /* fallback through other unlock styles */
283 #endif
284
285 #if defined(HAVE_TTYLOCK) || defined(HAVE_BAUDBOY)
286         if (ttyunlock ((char*) path)) {
287                 if (dev)
288                         gp_port_set_error (dev, _("Device '%s' could not be "
289                                            "unlocked."), path);
290                 return (GP_ERROR_IO_LOCK);
291         }
292 #elif defined(HAVE_LOCKDEV)
293
294         int pid;
295
296         pid = dev_unlock (path, 0);
297         if (pid) {
298                 if (dev) {
299                         if (pid > 0)
300                                 gp_port_set_error (dev, _("Device '%s' could "
301                                         "not be unlocked as it is locked by "
302                                         "pid %d."), path, pid);
303                         else
304                                 gp_port_set_error (dev, _("Device '%s' could "
305                                         "not be unlocked (dev_unlock "
306                                         "returned %d)"), path, pid);
307                 }
308                 return (GP_ERROR_IO_LOCK);
309         }
310 #endif /* !HAVE_LOCKDEV */
311
312         return (GP_OK);
313 }
314
315 int
316 gp_port_library_list (GPPortInfoList *list)
317 {
318         GPPortInfo info;
319         char path[1024], prefix[1024];
320         int x, fd;
321         struct stat s;
322 #ifdef OS2
323         int r, fh, option;
324 #endif
325
326         /* Copy in the serial port prefix */
327         strcpy (prefix, GP_PORT_SERIAL_PREFIX);
328
329         /* On Linux systems, check for devfs */
330 #ifdef __linux
331         if (!stat ("/dev/tts", &s))
332                 strcpy (prefix, "/dev/tts/%i");
333 #endif
334
335         for (x=GP_PORT_SERIAL_RANGE_LOW; x<=GP_PORT_SERIAL_RANGE_HIGH; x++) {
336                 sprintf (path, prefix, x);
337
338                 /* OS/2 seems to need an additional check */
339 #ifdef OS2
340                 r = DosOpen (path, &fh, &option, 0, 0, 1,
341                              OPEN_FLAGS_FAIL_ON_ERROR |
342                              OPEN_SHARE_DENYREADWRITE, 0);
343                 DosClose(fh);
344                 if (r)
345                         continue;
346 #endif
347                 /* Very first of all, if the device node is not there,
348                  * there is no need to try locking. */
349                 if ((stat (path, &s) == -1) && ((errno == ENOENT) || (errno == ENODEV)))
350                         continue;
351                 /* Just let it fail later on open, lock&open for just enumerating is taking too long. */
352                 /* This is a significant part of the "empty" startup time. */
353 #if 0
354                 /* First of all, try to lock the device */
355                 if (gp_port_serial_lock (NULL, path) < 0)
356                         continue;
357                         
358                 /* Device locked. Try to open the device. */
359                 fd = -1;
360 #ifdef HAVE_RESMGR
361                 /* resmgr has its own API, which calls to a server and
362                  * communicates over UNIX domain sockets.
363                  */
364                 fd = rsm_open_device(path, O_RDONLY | O_NDELAY);
365                 /* fall through to standard open if this failed */
366 #endif
367                 if (fd == -1)
368                         fd = open (path, O_RDONLY | O_NONBLOCK);
369                 if (fd < 0) {
370                         gp_port_serial_unlock (NULL, path);
371                         continue;
372                 }
373
374                 /*
375                  * Device locked and opened. Close it, unlock it, and add
376                  * it to the list.
377                  */
378                 close (fd);
379                 gp_port_serial_unlock (NULL, path);
380 #endif
381                 info.type = GP_PORT_SERIAL;
382                 strncpy (info.path, "serial:", sizeof (info.path));
383                 strncat (info.path, path, sizeof (info.path) - strlen (info.path) - 1);
384                 snprintf (info.name, sizeof (info.name),
385                           _("Serial Port %i"), x);
386                 CHECK (gp_port_info_list_append (list, info));
387         }
388
389         /*
390          * Generic support. Append it to the list without checking for
391          * return values, because this entry will not be counted.
392          */
393         info.type = GP_PORT_SERIAL;
394         strncpy (info.path, "^serial", sizeof (info.path));
395         memset (info.name, 0, sizeof (info.name));
396         gp_port_info_list_append (list, info);
397
398         return (GP_OK);
399 }
400
401 static int
402 gp_port_serial_init (GPPort *dev)
403 {
404         if (!dev)
405                 return (GP_ERROR_BAD_PARAMETERS);
406
407         dev->pl = malloc (sizeof (GPPortPrivateLibrary));
408         if (!dev->pl)
409                 return (GP_ERROR_NO_MEMORY);
410         memset (dev->pl, 0, sizeof (GPPortPrivateLibrary));
411
412         /* There is no default speed. */
413         dev->pl->baudrate = -1;
414
415         return GP_OK;
416 }
417
418 static int
419 gp_port_serial_exit (GPPort *dev)
420 {
421         if (!dev)
422                 return (GP_ERROR_BAD_PARAMETERS);
423
424         if (dev->pl) {
425                 free (dev->pl);
426                 dev->pl = NULL;
427         }
428
429         return GP_OK;
430 }
431
432 static int
433 gp_port_serial_open (GPPort *dev)
434 {
435         int result, max_tries = 5, i;
436 #ifdef OS2
437         int fd;
438 #endif
439         char *port;
440
441         /* Ports are named "serial:/dev/whatever/port" */
442         port = strchr (dev->settings.serial.port, ':');
443         if (!port)
444                 return GP_ERROR_UNKNOWN_PORT;
445         port++;
446
447         result = gp_port_serial_lock (dev, port);
448         if (result != GP_OK) {
449                 for (i = 0; i < max_tries; i++) {
450                         result = gp_port_serial_lock (dev, port);
451                         if (result == GP_OK)
452                                 break;
453                         gp_log (GP_LOG_DEBUG, "gphoto2-port-serial",
454                                 "Failed to get a lock, trying again...");
455                         sleep (1);
456                 }
457                 CHECK (result);
458         }
459         dev->pl->fd = -1;
460
461 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
462         dev->pl->fd = open (port, O_RDWR | O_NOCTTY | O_NONBLOCK);
463 #elif OS2
464         fd = open (port, O_RDWR | O_BINARY);
465         dev->pl->fd = open (port, O_RDWR | O_BINARY);
466         close(fd);
467 #else
468 # ifdef HAVE_RESMGR
469         dev->pl->fd = rsm_open_device (port, O_RDWR | O_NOCTTY | O_SYNC | O_NONBLOCK);
470         /* fall back trying old style open if not possible */
471 # endif
472         if (dev->pl->fd == -1)
473                 dev->pl->fd = open (port, O_RDWR | O_NOCTTY | O_SYNC | O_NONBLOCK);
474 #endif
475         if (dev->pl->fd == -1) {
476                 gp_port_set_error (dev, _("Failed to open '%s' (%m)."), port);
477                 dev->pl->fd = 0;
478                 return GP_ERROR_IO;
479         }
480
481         return GP_OK;
482 }
483
484 static int
485 gp_port_serial_close (GPPort *dev)
486 {
487         const char *path;
488
489         if (!dev)
490                 return (GP_OK);
491
492         if (dev->pl->fd) {
493                 if (close (dev->pl->fd) == -1) {
494                         gp_port_set_error (dev, _("Could not close "
495                                 "'%s' (%m)."), dev->settings.serial.port);
496                         return GP_ERROR_IO;
497                 }
498                 dev->pl->fd = 0;
499         }
500
501         /* Unlock the port */
502         path = strchr (dev->settings.serial.port, ':');
503         if (!path) return GP_ERROR_BAD_PARAMETERS;
504         path++;
505         CHECK (gp_port_serial_unlock (dev, path));
506
507 #if defined(__sgi)
508         /*
509          * On IRIX, we need to set the baudrate each time after opening
510          * the port.
511          */
512         dev->pl->baudrate = 0;
513 #endif
514
515         return GP_OK;
516 }
517
518 static int
519 gp_port_serial_write (GPPort *dev, const char *bytes, int size)
520 {
521         int len, ret;
522
523         if (!dev)
524                 return (GP_ERROR_BAD_PARAMETERS);
525
526         /* The device needs to be opened for that operation */
527         if (!dev->pl->fd)
528                 CHECK (gp_port_serial_open (dev));
529
530         /* Make sure we are operating at the specified speed */
531         CHECK (gp_port_serial_check_speed (dev));
532
533         len = 0;
534         while (len < size) {
535                 
536                 /*
537                  * Make sure we write all data while handling
538                  * the harmless errors
539                  */
540                 ret = write (dev->pl->fd, bytes, size - len);
541                 if (ret == -1) {
542                         switch (errno) {
543                         case EAGAIN:
544                         case EINTR:
545                                 ret = 0;
546                                 break;
547                         default:
548                                 gp_port_set_error (dev, _("Could not write "
549                                         "to port (%m)"));
550                                 return GP_ERROR_IO_WRITE;
551                         }
552                 }
553                 len += ret;
554         }
555
556         /* wait till all bytes are really sent */
557 #ifndef OS2
558 #ifdef HAVE_TERMIOS_H
559         tcdrain (dev->pl->fd);
560 #else
561         ioctl (dev->pl->fd, TCDRAIN, 0);
562 #endif
563 #endif
564         return GP_OK;
565 }
566
567
568 static int
569 gp_port_serial_read (GPPort *dev, char *bytes, int size)
570 {
571         struct timeval timeout;
572         fd_set readfs;          /* file descriptor set */
573         int readen = 0, now;
574
575         if (!dev)
576                 return (GP_ERROR_BAD_PARAMETERS);
577
578         /* The device needs to be opened for that operation */
579         if (!dev->pl->fd)
580                 CHECK (gp_port_serial_open (dev));
581
582         /* Make sure we are operating at the specified speed */
583         CHECK (gp_port_serial_check_speed (dev));
584
585         FD_ZERO (&readfs);
586         FD_SET (dev->pl->fd, &readfs);
587
588         while (readen < size) {
589
590                 /* Set timeout value within input loop */
591                 timeout.tv_usec = (dev->timeout % 1000) * 1000;
592                 timeout.tv_sec = (dev->timeout / 1000); 
593
594                 /* Any data available? */
595                 if (!select (dev->pl->fd + 1, &readfs, NULL, NULL, &timeout))
596                         return GP_ERROR_TIMEOUT;
597                 if (!FD_ISSET (dev->pl->fd, &readfs))
598                         return (GP_ERROR_TIMEOUT);
599
600                 if (dev->settings.serial.parity != GP_PORT_SERIAL_PARITY_OFF) {
601                     unsigned char ffchar[1];
602                     unsigned char nullchar[1];
603
604                     ffchar[0] = 0xff;
605                     nullchar[0] = 0;
606                     now = read (dev->pl->fd, bytes, 1);
607                     if (now < 0)
608                             return GP_ERROR_IO_READ;
609                     if (!memcmp(bytes,ffchar,1)) {
610                         now = read (dev->pl->fd, bytes, 1);
611                         if (now < 0)
612                                 return GP_ERROR_IO_READ;
613
614                         /* Parity errors are signaled by the serial layer
615                          * as 0xff 0x00 sequence.
616                          *
617                          * 0xff sent by the camera are escaped as
618                          * 0xff 0xff sequence. 
619                          *
620                          * All other 0xff 0xXX sequences are errors.
621                          *
622                          * cf. man tcsetattr, description of PARMRK.
623                          */
624                         if (!memcmp(bytes,nullchar,1)) {
625                             gp_port_set_error (dev, _("Parity error."));
626                             return GP_ERROR_IO_READ;
627                         }
628                         if (!memcmp(bytes,ffchar,1)) {
629                             gp_port_set_error (dev, _("Unexpected parity response sequence 0xff 0x%02x."), ((unsigned char*)bytes)[0]);
630                             return GP_ERROR_IO_READ;
631                         }
632                         /* Ok, we read 1 byte and it is 0xff */
633                         /* FALLTHROUGH */
634                     }
635                 } else {
636                     /* Just read the bytes */
637                     now = read (dev->pl->fd, bytes, size - readen);
638                     if (now < 0)
639                             return GP_ERROR_IO_READ;
640                 }
641                 bytes += now;
642                 readen += now;
643         }
644
645         return readen;
646 }
647
648 #ifdef HAVE_TERMIOS_H
649 static int
650 get_termios_bit (GPPort *dev, GPPin pin, int *bit)
651 {
652         switch (pin) {
653         case GP_PIN_RTS:
654                 *bit = TIOCM_RTS;
655                 break;
656         case GP_PIN_DTR:
657                 *bit = TIOCM_DTR;
658                 break;
659         case GP_PIN_CTS:
660                 *bit = TIOCM_CTS;
661                 break;
662         case GP_PIN_DSR:
663                 *bit = TIOCM_DSR;
664                 break;
665         case GP_PIN_CD:
666                 *bit = TIOCM_CD;
667                 break;
668         case GP_PIN_RING:
669                 *bit = TIOCM_RNG;
670                 break;
671         default:
672                 gp_port_set_error (dev, _("Unknown pin %i."), pin);
673                 return GP_ERROR_IO;
674         }
675         return (GP_OK);
676 }
677 #endif
678
679 static int
680 gp_port_serial_get_pin (GPPort *dev, GPPin pin, GPLevel *level)
681 {
682 #ifdef HAVE_TERMIOS_H
683         int j, bit;
684 #endif
685
686         if (!dev || !level)
687                 return (GP_ERROR_BAD_PARAMETERS);
688
689         *level = 0;
690
691 #ifdef HAVE_TERMIOS_H
692         CHECK (get_termios_bit (dev, pin, &bit));
693         if (ioctl (dev->pl->fd, TIOCMGET, &j) < 0) {
694                 gp_port_set_error (dev, _("Could not get level of pin %i "
695                                    "(%m)."), pin);
696                 return GP_ERROR_IO;
697         }
698         *level = j & bit;
699 #else
700 # ifdef __GCC__
701 #  warning ACCESSING PINS IS NOT IMPLEMENTED FOR NON-TERMIOS SYSTEMS!
702 # endif
703 #endif
704
705         return (GP_OK);
706 }
707
708 static int
709 gp_port_serial_set_pin (GPPort *dev, GPPin pin, GPLevel level)
710 {
711 #ifdef HAVE_TERMIOS_H
712         int bit, request;
713 #endif
714
715         if (!dev)
716                 return (GP_ERROR_BAD_PARAMETERS);
717
718 #ifdef HAVE_TERMIOS_H
719         CHECK (get_termios_bit (dev, pin, &bit));
720         switch (level) {
721         case GP_LEVEL_LOW:
722                 request = TIOCMBIS;
723                 break;
724         default:
725                 request = TIOCMBIC;
726                 break;
727         }
728         if (ioctl (dev->pl->fd, request, &bit) < 0) {
729                 gp_port_set_error (dev, _("Could not set level of pin %i to "
730                                    "%i (%m)."), pin, level);
731                 return GP_ERROR_IO;
732         }
733 #else
734 # ifdef __GCC__
735 #  warning ACCESSING PINS IS NOT IMPLEMENTED FOR NON-TERMIOS SYSTEMS!
736 # endif
737 #endif
738
739         return GP_OK;
740 }
741
742 static int
743 gp_port_serial_flush (GPPort *dev, int direction)
744 {
745         /* The device needs to be opened for that operation */
746         if (!dev->pl->fd)
747                 CHECK (gp_port_serial_open (dev));
748
749         /* Make sure we are operating at the specified speed */
750         CHECK (gp_port_serial_check_speed (dev));
751
752 #ifdef HAVE_TERMIOS_H
753         if (tcflush (dev->pl->fd, direction ? TCOFLUSH : TCIFLUSH) < 0) {
754                 gp_port_set_error (dev, _("Could not flush '%s' (%m)."),
755                         dev->settings.serial.port);
756                 return (GP_ERROR_IO);
757         }
758 #else
759 # ifdef __GCC__
760 #  warning SERIAL FLUSH NOT IMPLEMENTED FOR NON TERMIOS SYSTEMS!
761 # endif
762 #endif
763
764         return (GP_OK);
765 }
766
767 static speed_t
768 gp_port_serial_baudconv (int baudrate)
769 {
770 #define BAUDCASE(x)     case (x): { ret = B##x; break; }
771         speed_t ret;
772
773         switch (baudrate) {
774
775                 /* POSIX defined baudrates */
776                 BAUDCASE(0);
777                 BAUDCASE(50);
778                 BAUDCASE(75);
779                 BAUDCASE(110);
780                 BAUDCASE(134);
781                 BAUDCASE(150);
782                 BAUDCASE(200);
783                 BAUDCASE(300);
784                 BAUDCASE(600);
785                 BAUDCASE(1200);
786                 BAUDCASE(1800);
787                 BAUDCASE(2400);
788                 BAUDCASE(4800);
789                 BAUDCASE(9600);
790                 BAUDCASE(19200);
791                 BAUDCASE(38400);
792
793                 /* non POSIX values */
794 #ifdef B7200
795                 BAUDCASE(7200);
796 #endif
797 #ifdef B14400
798                 BAUDCASE(14400);
799 #endif
800 #ifdef B28800
801                 BAUDCASE(28800);
802 #endif
803 #ifdef B57600
804                 BAUDCASE(57600);
805 #endif
806 #ifdef B115200
807                 BAUDCASE(115200);
808 #endif
809 #ifdef B230400
810                 BAUDCASE(230400);
811 #endif
812         default:
813                 ret = (speed_t) baudrate;
814                 gp_log (GP_LOG_DEBUG, "gphoto2-port-serial", "Baudrate %d "
815                         "unknown - using as is", baudrate);
816         }
817
818         return ret;
819 #undef BAUDCASE
820 }
821
822 static int
823 gp_port_serial_check_speed (GPPort *dev)
824 {
825         speed_t speed;
826 #ifdef OS2
827         ULONG rc;
828         ULONG   ulParmLen = 2;     /* Maximum size of the parameter packet */
829 #else
830 #ifdef HAVE_TERMIOS_H
831         struct termios tio;
832 #else
833         struct sgttyb ttyb;
834 #endif
835 #endif
836
837         /*
838          * We need an open device in order to set the speed. If there is no
839          * open device, postpone setting of speed.
840          */
841         if (!dev->pl->fd)
842                 return (GP_OK);
843
844         /* If baudrate is up to date, do nothing */
845         if (dev->pl->baudrate == dev->settings.serial.speed)
846                 return (GP_OK);
847
848         gp_log (GP_LOG_DEBUG, "gphoto2-port-serial",
849                 "Setting baudrate to %d...", dev->settings.serial.speed);
850         speed = gp_port_serial_baudconv (dev->settings.serial.speed);
851
852 #ifdef OS2
853         rc = DosDevIOCtl (dev->pl->fd,       /* Device handle               */
854                           0x0001,            /* Serial-device control       */
855                           0x0043,            /* Sets bit rate               */
856                           (PULONG) &(dev->settings.serial.speed),
857                           sizeof(baudrate),  /* Max. size of parameter list */
858                           &ulParmLen,        /* Size of parameter packet    */
859                           NULL,              /* No data packet              */
860                           0,                 /* Maximum size of data packet */
861                           NULL);             /* Size of data packet         */
862         if(rc != 0)
863                 printf("DosDevIOCtl baudrate error:%d\n",rc);
864 #else /* !OS2 */
865 #ifdef HAVE_TERMIOS_H
866         if (tcgetattr(dev->pl->fd, &tio) < 0) {
867                 gp_port_set_error (dev, _("Could not set the baudrate to %d"),
868                                    dev->settings.serial.speed);
869                 return GP_ERROR_IO_SERIAL_SPEED;
870         }
871         tio.c_cflag = (tio.c_cflag & ~CSIZE) | CS8;
872
873         /* Set into raw, no echo mode */
874         tio.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL |
875                          IXANY | IXON | IXOFF | INPCK | ISTRIP);
876 #ifdef IUCLC
877         tio.c_iflag &= ~IUCLC;
878 #endif
879         tio.c_iflag |= (BRKINT | IGNPAR);
880         tio.c_oflag &= ~OPOST;
881         tio.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | ECHOE |
882                          ECHOK | IEXTEN);
883         tio.c_cflag &= ~(CRTSCTS | PARENB | PARODD);
884         tio.c_cflag |= CLOCAL | CREAD;
885
886         tio.c_cc[VMIN] = 1;
887         tio.c_cc[VTIME] = 0;
888
889         if (dev->settings.serial.parity != GP_PORT_SERIAL_PARITY_OFF) {
890             tio.c_iflag &= ~IGNPAR;
891             tio.c_iflag |= INPCK | PARMRK ;
892             tio.c_cflag |= PARENB;
893             if (dev->settings.serial.parity == GP_PORT_SERIAL_PARITY_ODD)
894                 tio.c_cflag |= PARODD;
895         }
896
897         /* Set the new speed. */
898         cfsetispeed (&tio, speed);
899         cfsetospeed (&tio, speed);
900         if (tcsetattr (dev->pl->fd, TCSANOW, &tio) < 0) {
901                 GP_DEBUG ("Error on 'tcsetattr'.");
902                 return GP_ERROR_IO_SERIAL_SPEED;
903         }
904
905         /* Clear O_NONBLOCK. */
906         if (fcntl (dev->pl->fd, F_SETFL, 0) < 0) {
907                 GP_DEBUG ("Error on 'fcntl'.");
908                 return GP_ERROR_IO_SERIAL_SPEED;
909         }
910
911         /*
912          * Verify if the speed change has been successful.
913          * This is needed because some Solaris systems just ignore unsupported
914          * speeds (like 115200) instead of complaining.
915          *
916          * Only perform the check if we really changed to some speed.
917          */
918         if (speed != B0) {
919                 if (tcgetattr (dev->pl->fd, &tio)) {
920                         GP_DEBUG ("Error on 'tcgetattr'.");
921                         return (GP_ERROR_IO_SERIAL_SPEED);
922                 }
923                 if ((cfgetispeed (&tio) != speed) ||
924                     (cfgetospeed (&tio) != speed)) {
925                         GP_DEBUG ("Cannot set baudrate to %d...",
926                                   dev->settings.serial.speed);
927                         return (GP_ERROR_NOT_SUPPORTED);
928                 }
929         }
930
931 #else /* !HAVE_TERMIOS_H */
932         if (ioctl (dev->pl->fd, TIOCGETP, &ttyb) < 0) {
933                 perror("ioctl(TIOCGETP)");
934                 return GP_ERROR_IO_SERIAL_SPEED;
935         }
936         ttyb.sg_ispeed = dev->settings.serial.speed;
937         ttyb.sg_ospeed = dev->settings.serial.speed;
938         ttyb.sg_flags = 0;
939
940         if (ioctl (dev->pl->fd, TIOCSETP, &ttyb) < 0) {
941                 perror("ioctl(TIOCSETP)");
942                 return GP_ERROR_IO_SERIAL_SPEED;
943         }
944 #endif
945 #endif
946
947         dev->pl->baudrate = dev->settings.serial.speed;
948         return GP_OK;
949 }
950
951 static int
952 gp_port_serial_update (GPPort *dev)
953 {
954         memcpy (&dev->settings, &dev->settings_pending, sizeof (dev->settings));
955
956         CHECK (gp_port_serial_check_speed (dev));
957
958         return GP_OK;
959 }
960
961 static int
962 gp_port_serial_send_break (GPPort *dev, int duration)
963 {
964         /* The device needs to be opened for that operation */
965         if (!dev->pl->fd)
966                 CHECK (gp_port_serial_open (dev));
967
968         /* Make sure we are operating at the specified speed */
969         CHECK (gp_port_serial_check_speed (dev));
970
971         /* Duration is in milliseconds */
972 #ifdef HAVE_TERMIOS_H
973         tcsendbreak (dev->pl->fd, duration / 310);
974         tcdrain (dev->pl->fd);
975 #else
976 # ifdef __GCC__
977 #  warning SEND BREAK NOT IMPLEMENTED FOR NON TERMIOS SYSTEMS!
978 # endif
979 #endif
980
981         return GP_OK;
982 }
983
984 GPPortOperations *
985 gp_port_library_operations ()
986 {
987         GPPortOperations *ops;
988
989         ops = malloc (sizeof (GPPortOperations));
990         if (!ops)
991                 return (NULL);
992         memset (ops, 0, sizeof (GPPortOperations)); 
993
994         ops->init   = gp_port_serial_init;
995         ops->exit   = gp_port_serial_exit;
996         ops->open   = gp_port_serial_open;
997         ops->close  = gp_port_serial_close;
998         ops->read   = gp_port_serial_read;
999         ops->write  = gp_port_serial_write;
1000         ops->update = gp_port_serial_update;
1001         ops->get_pin = gp_port_serial_get_pin;
1002         ops->set_pin = gp_port_serial_set_pin;
1003         ops->send_break = gp_port_serial_send_break;
1004         ops->flush  = gp_port_serial_flush;
1005
1006         return (ops);
1007 }