serial.c

Go to the documentation of this file.
00001 /*
00002  * $Id: serial.c,v 1.72 2006-10-12 14:21:22 desrod Exp $
00003  *
00004  * serial.c: Interface layer to serial HotSync connections
00005  *
00006  * Copyright (c) 1996, 1997, D. Jeff Dionne & Kenneth Albanowski
00007  * Copyright (c) 1999, Tilo Christ
00008  * Copyright (c) 2005, Florent Pillet
00009  *
00010  * This library is free software; you can redistribute it and/or modify it
00011  * under the terms of the GNU Library General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or (at
00013  * your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library
00018  * General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Library General Public License
00021  * along with this library; if not, write to the Free Software Foundation,
00022  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00023  *
00024  * -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
00025  */
00026 
00027 #ifdef HAVE_CONFIG_H
00028 #include <config.h>
00029 #endif
00030 
00031 #include <stdlib.h>
00032 #include <stdio.h>
00033 #include <signal.h>
00034 #include <fcntl.h>
00035 #include <string.h>
00036 #include <errno.h>
00037 #include <sys/types.h>
00038 #include <sys/socket.h>
00039 #include <sys/stat.h>
00040 #include <sys/time.h>           /* Needed for Redhat 6.x machines */
00041 #include <unistd.h>
00042 
00043 #include "pi-debug.h"
00044 #include "pi-source.h"
00045 #include "pi-socket.h"
00046 #include "pi-serial.h"
00047 #include "pi-net.h"
00048 #include "pi-cmp.h"
00049 #include "pi-error.h"
00050 #include "pi-util.h"
00051 
00052 #ifdef OS2
00053 #include <sys/select.h>
00054 #endif
00055 
00056 /* Declare prototypes */
00057 static int pi_serial_connect(pi_socket_t *ps, struct sockaddr *addr, 
00058                         size_t addrlen);
00059 static int pi_serial_bind(pi_socket_t *ps, struct sockaddr *addr,
00060                         size_t addrlen);
00061 static int pi_serial_listen(pi_socket_t *ps, int backlog);
00062 static int pi_serial_accept(pi_socket_t *ps, struct sockaddr *addr,
00063                         size_t *addrlen);
00064 static int pi_serial_getsockopt(pi_socket_t *ps, int level,
00065                         int option_name, void *option_value,
00066                         size_t *option_len);
00067 static int pi_serial_setsockopt(pi_socket_t *ps, int level,
00068                         int option_name, const void *option_value,
00069                         size_t *option_len);
00070 static int pi_serial_close(pi_socket_t *ps);
00071 
00072 extern int pi_socket_init(pi_socket_t *ps);
00073 
00074 
00075 /* Protocol Functions */
00076 /***********************************************************************
00077  *
00078  * Function:    pi_serial_protocol_dup
00079  *
00080  * Summary:     clones an existing pi_protocol struct
00081  *
00082  * Parameters:  pi_protocol*
00083  *
00084  * Returns:     pi_protocol_t* or NULL if operation failed
00085  *
00086  ***********************************************************************/
00087 static pi_protocol_t*
00088 pi_serial_protocol_dup (pi_protocol_t *prot)
00089 {
00090         pi_protocol_t *new_prot;
00091 
00092         ASSERT (prot != NULL);
00093         
00094         new_prot = (pi_protocol_t *) malloc(sizeof (pi_protocol_t));
00095 
00096         if (new_prot != NULL) {
00097                 new_prot->level         = prot->level;
00098                 new_prot->dup           = prot->dup;
00099                 new_prot->free          = prot->free;
00100                 new_prot->read          = prot->read;
00101                 new_prot->write         = prot->write;
00102                 new_prot->flush         = prot->flush;
00103                 new_prot->getsockopt    = prot->getsockopt;
00104                 new_prot->setsockopt    = prot->setsockopt;
00105                 new_prot->data          = NULL;
00106         }
00107 
00108         return new_prot;
00109 }
00110 
00111 
00112 /***********************************************************************
00113  *
00114  * Function:    pi_serial_protocol_free
00115  *
00116  * Summary:     frees an existing pi_protocol struct
00117  *
00118  * Parameters:  pi_protocol*
00119  *
00120  * Returns:     void
00121  *
00122  ***********************************************************************/
00123 static void
00124 pi_serial_protocol_free (pi_protocol_t *prot)
00125 {
00126         ASSERT (prot != NULL);
00127 
00128         if (prot != NULL)
00129                 free(prot);
00130 }
00131 
00132 
00133 /***********************************************************************
00134  *
00135  * Function:    pi_serial_protocol
00136  *
00137  * Summary:     creates and inits pi_protocol struct instance
00138  *
00139  * Parameters:  pi_device_t*
00140  *
00141  * Returns:     pi_protocol_t* or NULL if operation failed
00142  *
00143  ***********************************************************************/
00144 static pi_protocol_t*
00145 pi_serial_protocol (pi_device_t *dev)
00146 {       
00147         pi_protocol_t *prot;
00148         struct pi_serial_data *data;
00149 
00150         ASSERT (dev != NULL);
00151         
00152         prot = (pi_protocol_t *) malloc(sizeof (pi_protocol_t));
00153 
00154         data = (struct pi_serial_data *)(dev->data);
00155 
00156         if (prot != NULL) {
00157                 prot->level             = PI_LEVEL_DEV;
00158                 prot->dup               = pi_serial_protocol_dup;
00159                 prot->free              = pi_serial_protocol_free;
00160                 prot->read              = data->impl.read;
00161                 prot->write             = data->impl.write;
00162                 prot->flush             = data->impl.flush;
00163                 prot->getsockopt        = pi_serial_getsockopt;
00164                 prot->setsockopt        = pi_serial_setsockopt;
00165                 prot->data              = NULL;
00166         }
00167         
00168         return prot;
00169 }
00170 
00171 
00172 /* Device Functions */
00173 /***********************************************************************
00174  *
00175  * Function:    pi_serial_device_free
00176  *
00177  * Summary:     frees an existing pi_device struct
00178  *
00179  * Parameters:  pi_device_t*
00180  *
00181  * Returns:     void
00182  *
00183  ***********************************************************************/
00184 static void
00185 pi_serial_device_free (pi_device_t *dev) 
00186 {
00187         ASSERT (dev != NULL);
00188 
00189         free(dev->data);
00190         free(dev);
00191 }
00192 
00193 
00194 /***********************************************************************
00195  *
00196  * Function:    pi_serial_device
00197  *
00198  * Summary:     creates and inits pi_device struct instance 
00199  *
00200  * Parameters:  device type
00201  *
00202  * Returns:     pi_device_t* or NULL if operation failed
00203  *
00204  ***********************************************************************/
00205 pi_device_t*
00206 pi_serial_device (int type) 
00207 {
00208         pi_device_t *dev;
00209         struct  pi_serial_data *data;
00210         
00211         dev = (pi_device_t *) malloc(sizeof (pi_device_t));
00212         if (dev == NULL)
00213                 return NULL;
00214 
00215         data = (struct pi_serial_data *) malloc(sizeof (struct pi_serial_data));
00216         if (data == NULL) {
00217                 free(dev);
00218                 return NULL;
00219         }
00220 
00221         dev->free       = pi_serial_device_free;
00222         dev->protocol   = pi_serial_protocol;   
00223         dev->bind       = pi_serial_bind;
00224         dev->listen     = pi_serial_listen;
00225         dev->accept     = pi_serial_accept;
00226         dev->connect    = pi_serial_connect;
00227         dev->close      = pi_serial_close;
00228 
00229         switch (type) {
00230                 case PI_SERIAL_DEV:
00231                         pi_serial_impl_init (&data->impl);
00232                         break;
00233                 default:
00234                         pi_serial_impl_init (&data->impl);
00235                         break;
00236         }
00237         
00238         data->buf_size          = 0;
00239         data->rate              = -1;
00240         data->establishrate     = -1;
00241         data->establishhighrate = -1;
00242         data->timeout           = 0;
00243         data->rx_bytes          = 0;
00244         data->rx_errors         = 0;
00245         data->tx_bytes          = 0;
00246         data->tx_errors         = 0;
00247 
00248         dev->data               = data;
00249 
00250         return dev;
00251 }
00252 
00253 
00254 /***********************************************************************
00255  *
00256  * Function:    pi_serial_connect
00257  *
00258  * Summary:     Connect socket to a given address
00259  *
00260  * Parameters:  pi_socket*, sockaddr*, size_t
00261  *
00262  * Returns:     A negative number on error, 0 otherwise
00263  *
00264  ***********************************************************************/
00265 static int
00266 pi_serial_connect(pi_socket_t *ps, struct sockaddr *addr,
00267         size_t addrlen)
00268 {
00269         struct  pi_serial_data *data =
00270                 (struct pi_serial_data *)ps->device->data;
00271         struct  pi_sockaddr *pa = (struct pi_sockaddr *) addr;
00272         int err;
00273 
00274         if (ps->type == PI_SOCK_STREAM) {
00275                 if (ps->protocol == PI_PF_SYS) {
00276                         data->establishrate = data->rate = 57600;
00277                 } else {
00278                         if (data->establishrate == -1)
00279                                 get_pilot_rate(&data->establishrate, &data->establishhighrate);
00280 
00281                         /* Mandatory CMP connection rate */
00282                         data->rate = 9600;
00283                 }
00284         } else if (ps->type == PI_SOCK_RAW) {
00285                 /* Mandatory SysPkt connection rate */
00286                 data->establishrate = data->rate = 57600;
00287         }
00288 
00289         if ((err = data->impl.open(ps, pa, addrlen)) < 0)
00290                 return err;     /* errno already set */
00291 
00292         ps->raddr       = malloc(addrlen);
00293         memcpy(ps->raddr, addr, addrlen);
00294         ps->raddrlen    = addrlen;
00295         ps->laddr       = malloc(addrlen);
00296         memcpy(ps->laddr, addr, addrlen);
00297         ps->laddrlen    = addrlen;
00298 
00299         if (ps->type == PI_SOCK_STREAM) {
00300                 size_t  size;
00301                 switch (ps->cmd) {
00302                         case PI_CMD_CMP:
00303                                 if (cmp_tx_handshake(ps) < 0)
00304                                         goto fail;
00305 
00306                                 size = sizeof(data->rate);
00307                                 pi_getsockopt(ps->sd, PI_LEVEL_CMP, PI_CMP_BAUD,
00308                                                 &data->rate, &size);
00309 
00310                                 if ((err = data->impl.changebaud(ps)) < 0)
00311                                         goto fail;
00312                                 break;
00313                                 
00314                         case PI_CMD_NET:
00315                                 if ((err = data->impl.changebaud(ps)) < 0)
00316                                         goto fail;
00317                                 break;
00318                                 
00319                         case PI_CMD_SYS:
00320                                 if ((err = data->impl.changebaud(ps)) < 0)
00321                                         goto fail;
00322                                 break;
00323                 }
00324         }
00325         ps->state = PI_SOCK_CONN_INIT;
00326         ps->command = 0;
00327         return 0;
00328 
00329 fail:
00330         return err;
00331 }
00332 
00333 
00334 /***********************************************************************
00335  *
00336  * Function:    pi_serial_bind
00337  *
00338  * Summary:     Bind address to a local socket
00339  *
00340  * Parameters:  pi_socket*, sockaddr*, size_t
00341  *
00342  * Returns:     A negative number on error, 0 otherwise
00343  *
00344  ***********************************************************************/
00345 static int
00346 pi_serial_bind(pi_socket_t *ps, struct sockaddr *addr, size_t addrlen)
00347 {
00348         struct  pi_serial_data *data =
00349                         (struct pi_serial_data *)ps->device->data;
00350         struct  pi_sockaddr *pa = (struct pi_sockaddr *) addr;
00351         int err, count = 0;
00352 
00353         if (ps->type == PI_SOCK_STREAM) {
00354                 if (data->establishrate == -1)
00355                         get_pilot_rate(&data->establishrate, &data->establishhighrate);
00356 
00357                 /* Mandatory CMP connection rate */
00358                 data->rate = 9600;
00359         } else if (ps->type == PI_SOCK_RAW) {
00360                 /* Mandatory SysPkt connection rate */
00361                 data->establishrate = data->rate = 57600;
00362         }
00363 
00364 begin:
00365         if ((err = data->impl.open(ps, pa, addrlen)) < 0) {
00366                 int     save_errno = errno;
00367 #ifdef MAXPATHLEN
00368                 char    realport[MAXPATHLEN];
00369 #else
00370  # ifdef PATH_MAX
00371                 char    realport[PATH_MAX];
00372  # else
00373                 char    realport[4096];
00374  # endif /* PATH_MAX */
00375 #endif /* MAXPATHLEN */
00376 
00377                 realpath(pa->pi_device, realport);
00378                 errno = save_errno;
00379 
00380                 if (errno == ENOENT) {
00381                         LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
00382                                         " The device %s does not exist..\n",
00383                                         pa->pi_device));
00384                         LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
00385                                         " Possible solution:\n\n\tmknod %s c "
00386                                         "<major> <minor>\n\n", pa->pi_device));
00387                 } else if (errno == EACCES) {
00388                         LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
00389                                         "   Please check the "
00390                                         "permissions on %s..\n", realport));
00391                         LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
00392                                         " Possible solution:\n\n\tchmod 0666 "
00393                                         "%s\n\n", realport));
00394                 } else if (errno == ENODEV) {
00395                         while (count <= 5) {
00396                                 if (isatty(fileno(stdout))) {
00397                                         LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
00398                                                         "\r   Port not connected,"
00399                                                         " sleeping for 2 seconds, "));
00400                                         LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
00401                                                         "%d retries..",
00402                                                         5-count));
00403                                 }
00404                                 sleep(2);
00405                                 count++;
00406                                 goto begin;
00407                         }
00408                         LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
00409                                         "\n\n   Device not found on %s, \
00410                                         Did you hit HotSync?\n\n", realport));  
00411                 } else if (errno == EISDIR) {
00412                         LOG((PI_DBG_DEV, PI_DBG_LVL_ERR,
00413                                         " The port specified must"
00414                                         " contain a device name, and %s was"
00415                                         " a directory.\n"
00416                                         "   Please change that to reference a"
00417                                         " real device, and try"
00418                                         " again\n\n", pa->pi_device));
00419                 }
00420                 return err;
00421         }
00422         ps->raddr       = malloc(addrlen);
00423         memcpy(ps->raddr, addr, addrlen);
00424         ps->raddrlen    = addrlen;
00425         ps->laddr       = malloc(addrlen);
00426         memcpy(ps->laddr, addr, addrlen);
00427         ps->laddrlen    = addrlen;
00428 
00429         return 0;
00430 }
00431 
00432 /***********************************************************************
00433  *
00434  * Function:    pi_serial_listen
00435  *
00436  * Summary:     Prepare for incoming connections
00437  *
00438  * Parameters:  pi_socket*, backlog
00439  *
00440  * Returns:     0 for success, negative otherwise
00441  *
00442  ***********************************************************************/
00443 static int pi_serial_listen(pi_socket_t *ps, int backlog)
00444 {
00445         int     result;
00446         struct  pi_serial_data *data =
00447                 (struct pi_serial_data *)ps->device->data;
00448         
00449         /* ps->rate has been set by bind */
00450         result = data->impl.changebaud(ps);
00451         if (result == 0)
00452                 ps->state = PI_SOCK_LISTEN;
00453         
00454         return result;
00455 }
00456 
00457 /***********************************************************************
00458  *
00459  * Function:    pi_serial_accept
00460  *
00461  * Summary:     Accept an incoming connection
00462  *
00463  * Parameters:  pi_socket*, sockaddr*
00464  *
00465  * Returns:     Nothing
00466  *
00467  ***********************************************************************/
00468 static int
00469 pi_serial_accept(pi_socket_t *ps, struct sockaddr *addr,
00470         size_t *addrlen)
00471 {
00472         struct  pi_serial_data *data =
00473                 (struct pi_serial_data *)ps->device->data;
00474         size_t  size;
00475         int     err;
00476 
00477         /* Wait for data */
00478 #ifdef linux
00479         if (ps->accept_to) {
00480                 /* shield against losing the first packet */
00481                 int result = data->impl.poll(ps, 1000);
00482                 LOG((PI_DBG_DEV, PI_DBG_LVL_DEBUG, "%s: %d, poll result: %d.\n", __FILE__, __LINE__, result));
00483 
00484                 if (result < 0) {
00485                         char buf[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
00486                         data->impl.write(ps, buf, sizeof (buf), 1000);
00487                 }
00488         }
00489 #endif
00490         if ((err = data->impl.poll(ps, ps->accept_to * 1000)) < 0)
00491                 goto fail;
00492 
00493         data->timeout = ps->accept_to * 1000;
00494 
00495         pi_socket_init(ps);
00496         if (ps->type == PI_SOCK_STREAM) {
00497                 struct timeval tv;
00498                 unsigned char cmp_flags;
00499 
00500                 switch (ps->cmd) {
00501                         case PI_CMD_CMP:
00502                                 if ((err = cmp_rx_handshake(ps, data->establishrate, data->establishhighrate)) < 0)
00503                                         goto fail;
00504                                 
00505                                 /* propagate the long packet format flag to both command and non-command stacks */
00506                                 size = sizeof(cmp_flags);
00507                                 pi_getsockopt(ps->sd, PI_LEVEL_CMP, PI_CMP_FLAGS, &cmp_flags, &size);   
00508                                 if (cmp_flags & CMP_FL_LONG_PACKET_SUPPORT) {
00509                                         int use_long_format = 1;
00510                                         size = sizeof(int);
00511                                         pi_setsockopt(ps->sd, PI_LEVEL_PADP, PI_PADP_USE_LONG_FORMAT,
00512                                                       &use_long_format, &size);
00513                                         ps->command ^= 1;
00514                                         pi_setsockopt(ps->sd, PI_LEVEL_PADP, PI_PADP_USE_LONG_FORMAT,
00515                                                       &use_long_format, &size);
00516                                         ps->command ^= 1;
00517                                 }
00518                                         
00519                                         /* We always reconfigure our port, no matter what */
00520                                 size = sizeof(data->rate);
00521                                 pi_getsockopt(ps->sd, PI_LEVEL_CMP, PI_CMP_BAUD, &data->rate, &size);
00522                                 if ((err = data->impl.changebaud(ps)) < 0)
00523                                         goto fail;
00524                                         
00525                                 /* Palm device needs some time to reconfigure its port */
00526                                 tv.tv_sec       = 0;
00527                                 tv.tv_usec      = 50000;
00528                                 select(0, 0, 0, 0, &tv);
00529                                 break;
00530 
00531                         case PI_CMD_NET:
00532                                 /* serial/network: make sure we don't split writes. set socket option
00533                                  * on both the command and non-command instances of the protocol
00534                                  */
00535 #ifdef MACOSX
00536                                 /* We need to turn fragmentation OFF to improve Bluetooth performance
00537                                  * but this code is also used by USB on Linux and Freebsd
00538                                  * therefore, only compile it when running OS X
00539                                  */
00540                                 {
00541                                         int split = 0;
00542                                         size_t chunksize = 0;
00543 
00544                                         size = sizeof (split);
00545                                         pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_SPLIT_WRITES,
00546                                                 &split, &size);
00547                                         size = sizeof (chunksize);
00548                                         pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_WRITE_CHUNKSIZE,
00549                                                 &chunksize, &size);
00550 
00551                                         ps->command ^= 1;
00552                                         size = sizeof (split);
00553                                         pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_SPLIT_WRITES,
00554                                                 &split, &size);
00555                                         size = sizeof (chunksize);
00556                                         pi_setsockopt(ps->sd, PI_LEVEL_NET, PI_NET_WRITE_CHUNKSIZE,
00557                                                 &chunksize, &size);
00558                                         ps->command ^= 1;
00559                                 }
00560 #endif
00561                                 if ((err = net_rx_handshake(ps)) < 0)
00562                                         goto fail;
00563                                 break;
00564                 }
00565                 ps->dlprecord = 0;
00566         }
00567 
00568         data->timeout = 0;
00569         ps->command = 0;
00570         ps->state = PI_SOCK_CONN_ACCEPT;
00571 
00572         return ps->sd;
00573 
00574 fail:
00575         return err;
00576 }
00577 
00578 
00579 /***********************************************************************
00580  *
00581  * Function:    pi_serial_getsockopt
00582  *
00583  * Summary:     get options on socket
00584  *
00585  * Parameters:  pi_socket*, level, option name, option value, option length
00586  *
00587  * Returns:     0 for success, negative otherwise
00588  *
00589  ***********************************************************************/
00590 static int
00591 pi_serial_getsockopt(pi_socket_t *ps, int level, int option_name, 
00592                      void *option_value, size_t *option_len)
00593 {
00594         struct pi_serial_data *data =
00595                 (struct pi_serial_data *)ps->device->data;
00596 
00597         switch (option_name) {
00598                 case PI_DEV_RATE:
00599                         if (*option_len != sizeof (data->rate))
00600                                 goto error;
00601                         memcpy (option_value, &data->rate, sizeof (data->rate));
00602                         break;
00603 
00604                 case PI_DEV_ESTRATE:
00605                         if (*option_len != sizeof (data->establishrate))
00606                                 goto error;
00607                         memcpy (option_value, &data->establishrate, sizeof (data->establishrate));
00608                         break;
00609 
00610                 case PI_DEV_HIGHRATE:
00611                         if (*option_len != sizeof (data->establishhighrate))
00612                                 goto error;
00613                         memcpy (option_value, &data->establishhighrate, sizeof (data->establishhighrate));
00614                         break;
00615 
00616                 case PI_DEV_TIMEOUT:
00617                         if (*option_len != sizeof (data->timeout))
00618                                 goto error;
00619                         memcpy (option_value, &data->timeout, sizeof (data->timeout));
00620                         break;
00621         }
00622 
00623         return 0;
00624         
00625 error:
00626         errno = EINVAL;
00627         return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
00628 }
00629 
00630 
00631 /***********************************************************************
00632  *
00633  * Function:    pi_serial_setsockopt
00634  *
00635  * Summary:     set options on socket
00636  *
00637  * Parameters:  pi_socket*, level, option name, option value, option length
00638  *
00639  * Returns:     0 for success, negative otherwise
00640  *
00641  ***********************************************************************/
00642 static int
00643 pi_serial_setsockopt(pi_socket_t *ps, int level, int option_name, 
00644                      const void *option_value, size_t *option_len)
00645 {
00646         struct pi_serial_data *data =
00647                 (struct pi_serial_data *)ps->device->data;
00648 
00649         /* FIXME: can't change stuff if already connected */
00650         switch (option_name) {
00651                 case PI_DEV_ESTRATE:
00652                         if (*option_len != sizeof (data->establishrate))
00653                                 goto error;
00654                         memcpy (&data->establishrate, option_value, sizeof (data->establishrate));
00655                         break;
00656 
00657                 case PI_DEV_HIGHRATE:
00658                         if (*option_len != sizeof (data->establishhighrate))
00659                                 goto error;
00660                         memcpy (&data->establishhighrate, option_value, sizeof (data->establishhighrate));
00661                         break;
00662 
00663                 case PI_DEV_TIMEOUT:
00664                         if (*option_len != sizeof (data->timeout))
00665                                 goto error;
00666                         memcpy (&data->timeout, option_value, sizeof (data->timeout));
00667                         break;
00668         }
00669 
00670         return 0;
00671         
00672  error:
00673         errno = EINVAL;
00674         return pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
00675 }
00676 
00677 
00678 /***********************************************************************
00679  *
00680  * Function:    pi_serial_close
00681  *
00682  * Summary:     Close a connection, destroy the socket
00683  *
00684  * Parameters:  pi_socket*
00685  *
00686  * Returns:     always 0 for success
00687  *
00688  ***********************************************************************/
00689 static int pi_serial_close(pi_socket_t *ps)
00690 {
00691         struct pi_serial_data *data =
00692                 (struct pi_serial_data *)ps->device->data;
00693 
00694         if (ps->sd) {
00695                 data->impl.close (ps);
00696                 ps->sd = 0;
00697         }
00698 
00699         if (ps->laddr) {
00700                 free(ps->laddr);
00701                 ps->laddr = NULL;
00702         }
00703 
00704         if (ps->raddr) {
00705                 free(ps->raddr);
00706                 ps->raddr = NULL;
00707         }
00708 
00709         return 0;
00710 }
00711 
00712 /* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
00713 /* ex: set tabstop=4 expandtab: */
00714 /* Local Variables: */
00715 /* indent-tabs-mode: t */
00716 /* c-basic-offset: 8 */
00717 /* End: */

© 1996-2007 by pilot-link.org. All rights reserved.