"Fossies" - the Fresh Open Source Software Archive

Member "libgphoto2-2.5.27/libgphoto2_port/serial/unix.c" (31 Jan 2021, 24208 Bytes) of package /linux/privat/libgphoto2-2.5.27.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "unix.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.5.26_vs_2.5.27.

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