mb_rtu.c
author Edouard Tisserant <edouard.tisserant@gmail.com>
Mon, 07 Jun 2021 11:21:26 +0200
changeset 17 e319814f1c17
parent 15 cadd89d14ca5
permissions -rw-r--r--
merge
0
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     1
/*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     2
 * Copyright (c) 2001,2016 Mario de Sousa (msousa@fe.up.pt)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     3
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     4
 * This file is part of the Modbus library for Beremiz and matiec.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     5
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     6
 * This Modbus library is free software: you can redistribute it and/or modify
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     7
 * it under the terms of the GNU Lesser General Public License as published by
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     8
 * the Free Software Foundation, either version 3 of the License, or
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
     9
 * (at your option) any later version.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    10
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    11
 * This program is distributed in the hope that it will be useful, but
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    14
 * General Public License for more details.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    15
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    16
 * You should have received a copy of the GNU Lesser General Public License
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    17
 * along with this Modbus library.  If not, see <http://www.gnu.org/licenses/>.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    18
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    19
 * This code is made available on the understanding that it will not be
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    20
 * used in safety-critical situations without a full and competent review.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    21
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    22
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    23
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    24
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    25
#include <fcntl.h>      /* File control definitions */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    26
#include <stdio.h>      /* Standard input/output */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    27
#include <string.h>
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    28
#include <stdlib.h>
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    29
#include <termio.h>     /* POSIX terminal control definitions */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    30
#include <sys/time.h>   /* Time structures for select() */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    31
#include <unistd.h>     /* POSIX Symbolic Constants */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    32
#include <assert.h>
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    33
#include <errno.h>      /* Error definitions */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    34
#include <time.h>       /* clock_gettime()   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    35
#include <limits.h>     /* required for INT_MAX */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    36
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    37
#include <netinet/in.h> /* required for htons() and ntohs() */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    38
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    39
#include "mb_layer1.h"  /* The public interface this file implements... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    40
#include "mb_rtu_private.h"
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    41
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    42
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    43
#define ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    44
#define ERRMSG_HEAD "ModbusRTU: "
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    45
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    46
// #define DEBUG   /* uncomment to see the data sent and received */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    47
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    48
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    49
#ifndef ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    50
#define ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    51
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    52
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    53
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    54
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    55
#define SAFETY_MARGIN 10
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    56
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    57
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    58
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    59
/** Include common code...         **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    60
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    61
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    62
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    63
#include "mb_ds_util.h"    /* data structures... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    64
#include "mb_time_util.h"  /* time conversion routines... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    65
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    66
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    67
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    68
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    69
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    70
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    71
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    72
/****                Forward Declarations                  ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    73
/****                    and Defaults                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    74
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    75
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    76
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    77
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    78
 /* CRC funtions... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    79
typedef u16 (*crc_func_t)(u8 *buf, int cnt);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    80
static u16 crc_slow(u8 *buf, int cnt);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    81
static u16 crc_fast(u8 *buf, int cnt);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    82
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    83
 /* slow version does not need to be initialised, so we use it as default. */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    84
#define DEF_CRC_FUNCTION crc_slow
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    85
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    86
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    87
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    88
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    89
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    90
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    91
/****              Local Utility functions...              ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    92
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    93
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    94
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    95
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    96
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    97
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    98
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
    99
/** Miscelaneous Utility functions **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   100
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   101
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   102
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   103
/*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   104
 * Functions to convert u16 variables
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   105
 * between network and host byte order
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   106
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   107
 * NOTE: Modbus uses MSByte first, just like
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   108
 *       tcp/ip, so we use the htons() and
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   109
 *       ntoh() functions to guarantee
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   110
 *       code portability.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   111
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   112
static inline u16 mb_hton(u16 h_value) 
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   113
  {return htons(h_value);} /*  return h_value; */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   114
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   115
static inline u16 mb_ntoh(u16 m_value)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   116
  {return ntohs(m_value);} /*  return m_value; */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   117
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   118
/*  return Most Significant Byte of value; */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   119
static inline u8 msb(u16 value)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   120
  {return (value >> 8) & 0xFF;}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   121
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   122
/*  return Least Significant Byte of value; */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   123
static inline u8 lsb(u16 value)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   124
  {return value & 0xFF;}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   125
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   126
#define u16_v(char_ptr)  (*((u16 *)(&(char_ptr))))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   127
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   128
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   129
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   130
/**************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   131
/**                                  **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   132
/**    Initialise a termios struct   **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   133
/**                                  **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   134
/**************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   135
static int termios_init(struct termios *tios,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   136
                        int baud,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   137
                        int parity,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   138
                        int data_bits,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   139
                        int stop_bits) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   140
  speed_t baud_rate;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   141
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   142
  if (tios == NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   143
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   144
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   145
  /* reset all the values... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   146
  /* NOTE: the following are initialised later on...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   147
  tios->c_iflag = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   148
  tios->c_oflag = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   149
  tios->c_cflag = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   150
  tios->c_lflag = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   151
  */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   152
  tios->c_line  = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   153
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   154
 /* The minimum number of characters that should be received
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   155
  * to satisfy a call to read().
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   156
  */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   157
  tios->c_cc[VMIN ] = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   158
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   159
 /* The maximum inter-arrival interval between two characters,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   160
  * in deciseconds.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   161
  *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   162
  * NOTE: we could use this to detect the end of RTU frames,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   163
  *       but we prefer to use select() that has higher resolution,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   164
  *       even though this higher resolution is most probably not
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   165
  *       supported, and the effective resolution is 10ms,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   166
  *       one tenth of a decisecond.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   167
  */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   168
  tios->c_cc[VTIME] = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   169
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   170
  /* configure the input modes... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   171
  tios->c_iflag =  IGNBRK |  /* ignore BREAK condition on input         */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   172
                   IGNPAR |  /* ignore framing errors and parity errors */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   173
                   IXANY;    /* enable any character to restart output  */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   174
  /*               BRKINT       Only active if IGNBRK is not set.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   175
   *                            generate SIGINT on BREAK condition,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   176
   *                            otherwise read BREAK as character \0.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   177
   *               PARMRK       Only active if IGNPAR is not set.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   178
   *                            replace bytes with parity errors with
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   179
   *                            \377 \0, instead of \0.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   180
   *               INPCK        enable input parity checking
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   181
   *               ISTRIP       strip off eighth bit
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   182
   *               IGNCR        ignore carriage return on input
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   183
   *               INLCR        only active if IGNCR is not set.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   184
   *                            translate newline to carriage return  on input
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   185
   *               ICRNL        only active if IGNCR is not set.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   186
   *                            translate carriage return to newline on input
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   187
   *               IUCLC        map uppercase characters to lowercase on input
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   188
   *               IXON         enable XON/XOFF flow control on output
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   189
   *               IXOFF        enable XON/XOFF flow control on input
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   190
   *               IMAXBEL      ring bell when input queue is full
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   191
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   192
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   193
  /* configure the output modes... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   194
  tios->c_oflag = OPOST;     /* enable implementation-defined output processing */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   195
  /*              ONOCR         don't output CR at column 0
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   196
   *              OLCUC         map lowercase characters to uppercase on output
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   197
   *              ONLCR         map NL to CR-NL on output
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   198
   *              OCRNL         map CR to NL on output
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   199
   *              OFILL         send fill characters for a delay, rather than
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   200
   *                            using a timed delay
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   201
   *              OFDEL         fill character is ASCII DEL. If unset, fill
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   202
   *                            character is ASCII NUL
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   203
   *              ONLRET        don't output CR
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   204
   *              NLDLY         NL delay mask. Values are NL0 and NL1.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   205
   *              CRDLY         CR delay mask. Values are CR0, CR1, CR2, or CR3.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   206
   *              TABDLY        horizontal tab delay mask. Values are TAB0, TAB1,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   207
   *                            TAB2, TAB3, or XTABS. A value of XTABS expands
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   208
   *                            tabs to spaces (with tab stops every eight columns).
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   209
   *              BSDLY         backspace delay mask. Values are BS0 or BS1.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   210
   *              VTDLY         vertical tab delay mask. Values are VT0 or VT1.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   211
   *              FFDLY         form feed delay mask. Values are FF0 or FF1.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   212
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   213
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   214
  /* configure the control modes... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   215
  tios->c_cflag = CREAD |    /* enable receiver.               */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   216
                  CLOCAL;    /* ignore modem control lines     */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   217
  /*              HUPCL         lower modem control lines after last process
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   218
   *                            closes the device (hang up).
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   219
   *              CRTSCTS       flow control (Request/Clear To Send).
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   220
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   221
       if (data_bits == 5) tios->c_cflag |= CS5;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   222
  else if (data_bits == 6) tios->c_cflag |= CS6;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   223
  else if (data_bits == 7) tios->c_cflag |= CS7;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   224
  else if (data_bits == 8) tios->c_cflag |= CS8;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   225
  else return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   226
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   227
       if (stop_bits == 1) tios->c_cflag &=~ CSTOPB;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   228
  else if (stop_bits == 2) tios->c_cflag |= CSTOPB;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   229
  else return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   230
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   231
         if(parity == 0) { /* none */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   232
    tios->c_cflag &=~ PARENB;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   233
    tios->c_cflag &=~ PARODD;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   234
  } else if(parity == 2)  { /* even */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   235
    tios->c_cflag |=  PARENB;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   236
    tios->c_cflag &=~ PARODD;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   237
  } else if(parity == 1)  { /* odd */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   238
    tios->c_cflag |=  PARENB;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   239
    tios->c_cflag |=  PARODD;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   240
  } else return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   241
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   242
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   243
  /* configure the local modes... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   244
  tios->c_lflag = IEXTEN;    /* enable implementation-defined input processing   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   245
  /*              ISIG          when any of the characters INTR, QUIT, SUSP, or DSUSP
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   246
   *                            are received, generate the corresponding signal.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   247
   *              ICANON        enable canonical mode. This enables the special
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   248
   *                            characters EOF, EOL, EOL2, ERASE, KILL, REPRINT,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   249
   *                            STATUS, and WERASE, and buffers by lines.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   250
   *              ECHO          echo input characters.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   251
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   252
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   253
  /* Set the baud rate */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   254
  /* Must be done before reseting all the values to 0! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   255
  switch(baud) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   256
    case 110:    baud_rate = B110;    break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   257
    case 300:    baud_rate = B300;    break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   258
    case 600:    baud_rate = B600;    break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   259
    case 1200:   baud_rate = B1200;   break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   260
    case 2400:   baud_rate = B2400;   break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   261
    case 4800:   baud_rate = B4800;   break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   262
    case 9600:   baud_rate = B9600;   break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   263
    case 19200:  baud_rate = B19200;  break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   264
    case 38400:  baud_rate = B38400;  break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   265
    case 57600:  baud_rate = B57600;  break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   266
    case 115200: baud_rate = B115200; break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   267
    default: return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   268
  } /* switch() */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   269
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   270
  if ((cfsetispeed(tios, baud_rate) < 0) ||
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   271
      (cfsetospeed(tios, baud_rate) < 0))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   272
    return -1;;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   273
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   274
  return 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   275
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   276
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   277
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   278
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   279
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   280
/** A data structure - recv buffer **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   281
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   282
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   283
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   284
/* A data structutre used for the receive buffer, i.e. the buffer
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   285
 * that stores the bytes we receive from the bus.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   286
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   287
 * What we realy needed here is an unbounded buffer. This may be
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   288
 * implemented by:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   289
 *   - a circular buffer the size of the maximum frame length
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   290
 *   - a linear buffer somewhat larger than the maximum frame length
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   291
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   292
 * Due to the fact that this library's API hands over the frame data
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   293
 * in a linear buffer, and also reads the data (i,e, calls to read())
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   294
 * into a linear buffer:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   295
 *  - the circular buffer would be more efficient in aborted frame
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   296
 *    situations
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   297
 *  - the linear is more efficient when no aborted frames are recieved.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   298
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   299
 * I have decided to optimize for the most often encountered situation,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   300
 * i.e. when no aborted frames are received.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   301
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   302
 * The linear buffer has a size larger than the maximum
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   303
 * number of bytes we intend to store in it. We simply start ignoring
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   304
 * the first bytes in the buffer in which we are not interested in, and
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   305
 * continue with the extra bytes of the buffer. When we reach the limit
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   306
 * of these extra bytes, we shift the data down so it once again
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   307
 * uses the first bytes of the buffer. The more number of extra bytes,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   308
 * the more efficient it will be.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   309
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   310
 * Note that if we don't receive any aborted frames, it will work as a
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   311
 * simple linear buffer, and no memory shifts will be required!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   312
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   313
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   314
typedef struct {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   315
        lb_buf_t data_buf;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   316
          /* Flag:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   317
            *  1 => We have detected a frame boundary using 3.5 character silence
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   318
            *  0 => We have not yet detected any frame boundary
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   319
           */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   320
        int found_frame_boundary; /* ==1 => valid data ends at a frame boundary. */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   321
          /* Flag:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   322
            *  Used in the call to search_for_frame() as the history parameter!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   323
           */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   324
        int frame_search_history;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   325
        } recv_buf_t;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   326
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   327
/* A small auxiliary function... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   328
static inline u8 *recv_buf_init(recv_buf_t *buf, int size, int max_data_start) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   329
  buf->found_frame_boundary = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   330
  buf->frame_search_history = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   331
  return lb_init(&buf->data_buf, size, max_data_start);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   332
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   333
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   334
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   335
/* A small auxiliary function... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   336
static inline void recv_buf_done(recv_buf_t *buf) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   337
  buf->found_frame_boundary = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   338
  buf->frame_search_history = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   339
  lb_done(&buf->data_buf);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   340
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   341
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   342
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   343
/* A small auxiliary function... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   344
static inline void recv_buf_reset(recv_buf_t *buf) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   345
  buf->found_frame_boundary = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   346
  buf->frame_search_history = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   347
  lb_data_purge_all(&buf->data_buf);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   348
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   349
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   350
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   351
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   352
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   353
/**  A data structure - nd entry   **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   354
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   355
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   356
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   357
/* NOTE: nd = node descriptor */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   358
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   359
typedef struct {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   360
         /* The file descriptor associated with this node */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   361
         /* NOTE: if the node is not yet in use, i.e. if the node is free,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   362
          *       then fd will be set to -1
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   363
          */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   364
        int    fd;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   365
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   366
         /* the time it takes to transmit 1.5 characters at the current baud rate */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   367
        struct timeval time_15_char_;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   368
         /* the time it takes to transmit 3.5 characters at the current baud rate */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   369
        struct timeval time_35_char_;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   370
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   371
         /* Due to the algorithm used to work around aborted frames, the modbus_read()
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   372
          * function might read beyond the current modbus frame. The extra bytes
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   373
          * must be stored for the subsequent call to modbus_read().
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   374
          */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   375
        recv_buf_t recv_buf_;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   376
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   377
          /* The old settings of the serial port, to be reset when the library is closed... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   378
        struct termios old_tty_settings_;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   379
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   380
          /* ignore echo flag.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   381
           * If set to 1, then it means that we will be reading every byte we
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   382
           * ourselves write out to the bus, so we must ignore those bytes read
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   383
           * before we really read the data sent by remote nodes.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   384
           *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   385
           * This comes in useful when using a RS232-RS485 converter that does
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   386
           * not correctly control the RTS-CTS lines...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   387
           */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   388
        int ignore_echo;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   389
 } nd_entry_t;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   390
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   391
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   392
static inline void nd_entry_init(nd_entry_t *nde) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   393
  nde->fd = -1; /* The node is free... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   394
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   395
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   396
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   397
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   398
static int nd_entry_connect(nd_entry_t *nde,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   399
                            node_addr_t *node_addr,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   400
                            optimization_t opt) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   401
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   402
  int parity_bits, start_bits, char_bits;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   403
  struct termios settings;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   404
  int buf_size;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   405
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   406
  /*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   407
  if (nde == NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   408
    goto error_exit_0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   409
  */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   410
  if (nde->fd >= 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   411
    goto error_exit_0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   412
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   413
  /* initialise the termios data structure */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   414
  if (termios_init(&settings,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   415
                   node_addr->addr.rtu.baud,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   416
                   node_addr->addr.rtu.parity,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   417
                   node_addr->addr.rtu.data_bits,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   418
                   node_addr->addr.rtu.stop_bits)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   419
      < 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   420
#ifdef ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   421
    fprintf(stderr, ERRMSG_HEAD "Invalid serial line settings"
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   422
                    "(baud=%d, parity=%d, data_bits=%d, stop_bits=%d)\n",
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   423
                    node_addr->addr.rtu.baud,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   424
                    node_addr->addr.rtu.parity,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   425
                    node_addr->addr.rtu.data_bits,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   426
                    node_addr->addr.rtu.stop_bits);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   427
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   428
    goto error_exit_1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   429
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   430
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   431
    /* set the ignore_echo flag */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   432
  nde->ignore_echo = node_addr->addr.rtu.ignore_echo;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   433
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   434
    /* initialise recv buffer */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   435
  buf_size = (opt == optimize_size)?RECV_BUFFER_SIZE_SMALL:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   436
                                    RECV_BUFFER_SIZE_LARGE;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   437
  if (recv_buf_init(&nde->recv_buf_, buf_size, buf_size - MAX_RTU_FRAME_LENGTH)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   438
      == NULL) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   439
#ifdef ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   440
    fprintf(stderr, ERRMSG_HEAD "Out of memory: error initializing receive buffer\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   441
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   442
    goto error_exit_2;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   443
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   444
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   445
    /* open the serial port */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   446
  if((nde->fd = open(node_addr->addr.rtu.device, O_RDWR | O_NOCTTY | O_NDELAY))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   447
     < 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   448
#ifdef ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   449
    perror("open()");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   450
    fprintf(stderr, ERRMSG_HEAD "Error opening device %s\n",
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   451
                   node_addr->addr.rtu.device);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   452
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   453
    goto error_exit_3;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   454
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   455
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   456
  if(tcgetattr(nde->fd, &nde->old_tty_settings_) < 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   457
#ifdef ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   458
    perror("tcgetattr()");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   459
    fprintf(stderr, ERRMSG_HEAD "Error reading device's %s original settings.\n",
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   460
                      node_addr->addr.rtu.device);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   461
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   462
    goto error_exit_4;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   463
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   464
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   465
  if(tcsetattr(nde->fd, TCSANOW, &settings) < 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   466
#ifdef ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   467
    perror("tcsetattr()");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   468
    fprintf(stderr, ERRMSG_HEAD "Error configuring device %s "
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   469
                    "(baud=%d, parity=%d, data_bits=%d, stop_bits=%d)\n",
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   470
                    node_addr->addr.rtu.device,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   471
                    node_addr->addr.rtu.baud,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   472
                    node_addr->addr.rtu.parity,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   473
                    node_addr->addr.rtu.data_bits,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   474
                    node_addr->addr.rtu.stop_bits);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   475
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   476
    goto error_exit_4;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   477
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   478
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   479
  parity_bits   = (node_addr->addr.rtu.parity == 0)?0:1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   480
  start_bits    = 1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   481
  char_bits     = start_bits  + node_addr->addr.rtu.data_bits +
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   482
                  parity_bits + node_addr->addr.rtu.stop_bits;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   483
  nde->time_15_char_ = d_to_timeval(SAFETY_MARGIN*1.5*char_bits/node_addr->addr.rtu.baud);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   484
  nde->time_35_char_ = d_to_timeval(SAFETY_MARGIN*3.5*char_bits/node_addr->addr.rtu.baud);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   485
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   486
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   487
  fprintf(stderr, "nd_entry_connect(): %s ope{.node=NULL, .node_count=0};n\n", node_addr->addr.rtu.device );
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   488
  fprintf(stderr, "nd_entry_connect(): returning fd=%d\n", nde->fd);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   489
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   490
  return nde->fd;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   491
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   492
  error_exit_4:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   493
    close(nde->fd);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   494
  error_exit_3:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   495
    recv_buf_done(&nde->recv_buf_);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   496
  error_exit_2:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   497
  error_exit_1:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   498
    nde->fd = -1; /* set the node as free... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   499
  error_exit_0:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   500
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   501
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   502
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   503
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   504
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   505
static int nd_entry_free(nd_entry_t *nde) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   506
  if (nde->fd < 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   507
    /* already free */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   508
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   509
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   510
  /* reset the tty device old settings... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   511
#ifdef ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   512
  int res =
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   513
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   514
            tcsetattr(nde->fd, TCSANOW, &nde->old_tty_settings_);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   515
#ifdef ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   516
  if(res < 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   517
    fprintf(stderr, ERRMSG_HEAD "Error reconfiguring serial port to it's original settings.\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   518
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   519
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   520
  recv_buf_done(&nde->recv_buf_);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   521
  close(nde->fd);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   522
  nde->fd = -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   523
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   524
  return 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   525
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   526
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   527
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   528
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   529
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   530
static inline int nd_entry_is_free(nd_entry_t *nde) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   531
  return (nde->fd < 0);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   532
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   533
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   534
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   535
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   536
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   537
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   538
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   539
/**  A data structure - nd table   **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   540
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   541
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   542
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   543
typedef struct {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   544
      /* the array of node descriptors, and current size... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   545
    nd_entry_t *node;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   546
    int        node_count;      /* total number of nodes in the node[] array */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   547
} nd_table_t;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   548
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   549
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   550
#if 1
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   551
/* nd_table_init()
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   552
 *   Version 1 of the nd_table_init() function. 
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   553
 *   If called more than once, 2nd and any subsequent calls will
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   554
 *   be interpreted as a request to confirm that it was already correctly 
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   555
 *   initialized with the requested number of nodes.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   556
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   557
static int nd_table_init(nd_table_t *ndt, int nd_count) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   558
  int count;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   559
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   560
  if (ndt->node != NULL) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   561
    /* this function has already been called, and the node table is already initialised */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   562
    return (ndt->node_count == nd_count)?0:-1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   563
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   564
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   565
  /* initialise the node descriptor metadata array... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   566
  ndt->node = malloc(sizeof(nd_entry_t) * nd_count);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   567
  if (ndt->node == NULL) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   568
#ifdef ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   569
    fprintf(stderr, ERRMSG_HEAD "Out of memory: error initializing node address buffer\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   570
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   571
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   572
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   573
  ndt->node_count = nd_count;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   574
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   575
    /* initialise the state of each node in the array... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   576
  for (count = 0; count < ndt->node_count; count++) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   577
    nd_entry_init(&ndt->node[count]);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   578
  } /* for() */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   579
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   580
  return nd_count; /* number of succesfully created nodes! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   581
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   582
#else
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   583
/* nd_table_init()
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   584
 *   Version 2 of the nd_table_init() function. 
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   585
 *   If called more than once, 2nd and any subsequent calls will
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   586
 *   be interpreted as a request to reserve an extra new_nd_count
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   587
 *   number of nodes. This will be done using realloc().
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   588
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   589
static int nd_table_init(nd_table_t *ndt, int new_nd_count) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   590
  int count;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   591
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   592
  /* initialise the node descriptor metadata array... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   593
  ndt->node = realloc(ndt->node, sizeof(nd_entry_t) * (ndt->node_count + new_nd_count));
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   594
  if (ndt->node == NULL) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   595
#ifdef ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   596
    fprintf(stderr, ERRMSG_HEAD "Out of memory: error initializing node address buffer\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   597
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   598
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   599
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   600
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   601
  /* initialise the state of each newly added node in the array... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   602
  for (count = ndt->node_count; count < ndt->node_count + new_nd_count; count++) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   603
    nd_entry_init(&ndt->node[count]);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   604
  } /* for() */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   605
  ndt->node_count += new_nd_count;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   606
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   607
  return new_nd_count; /* number of succesfully created nodes! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   608
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   609
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   610
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   611
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   612
static inline nd_entry_t *nd_table_get_nd(nd_table_t *ndt, int nd) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   613
  if ((nd < 0) || (nd >= ndt->node_count))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   614
    return NULL;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   615
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   616
  return &ndt->node[nd];
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   617
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   618
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   619
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   620
static inline void nd_table_done(nd_table_t *ndt) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   621
  int i;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   622
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   623
  if (ndt->node == NULL) 
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   624
    return;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   625
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   626
    /* close all the connections... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   627
  for (i = 0; i < ndt->node_count; i++)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   628
    nd_entry_free(&ndt->node[i]);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   629
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   630
  /* Free memory... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   631
  free(ndt->node);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   632
  *ndt = (nd_table_t){.node=NULL, .node_count=0};
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   633
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   634
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   635
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   636
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   637
static inline int nd_table_get_free_nd(nd_table_t *ndt) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   638
  int count;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   639
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   640
  for (count = 0; count < ndt->node_count; count++) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   641
    if (nd_entry_is_free(&ndt->node[count]))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   642
      return count;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   643
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   644
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   645
   /* none found... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   646
  return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   647
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   648
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   649
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   650
static inline int nd_table_free_nd(nd_table_t *ndt, int nd) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   651
  if ((nd < 0) || (nd >= ndt->node_count))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   652
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   653
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   654
  return nd_entry_free(&ndt->node[nd]);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   655
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   656
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   657
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   658
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   659
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   660
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   661
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   662
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   663
/****                Global Library State                  ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   664
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   665
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   666
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   667
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   668
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   669
 /* The node descriptor table... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   670
 /* NOTE: This variable must be correctly initialised here!! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   671
static nd_table_t nd_table_ = {.node=NULL, .node_count=0};
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   672
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   673
 /* The optimization choice... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   674
static optimization_t optimization_;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   675
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   676
 /* the crc function currently in use... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   677
 /* This will depend on the optimisation choice... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   678
crc_func_t crc_calc = DEF_CRC_FUNCTION;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   679
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   680
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   681
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   682
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   683
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   684
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   685
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   686
/****                      CRC functions                   ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   687
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   688
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   689
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   690
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   691
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   692
#if     RTU_FRAME_CRC_LENGTH < 2
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   693
#error  The CRC on modbus RTU frames requires at least 2 bytes in the frame length.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   694
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   695
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   696
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   697
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   698
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   699
/**     Read the CRC of a frame    **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   700
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   701
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   702
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   703
/* NOTE: cnt is number of bytes in the frame _excluding_ CRC! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   704
static inline u16 crc_read(u8 *buf, int cnt) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   705
  /* For some strange reason, the crc is transmited
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   706
   * LSB first, unlike all other values...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   707
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   708
  return (buf[cnt + 1] << 8) | buf[cnt];
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   709
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   710
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   711
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   712
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   713
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   714
/**    Write the CRC of a frame    **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   715
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   716
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   717
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   718
/* NOTE: cnt is number of bytes in the frame _excluding_ CRC! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   719
static inline void crc_write(u8 *buf, int cnt) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   720
  /* For some strange reason, the crc is transmited
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   721
   * LSB first, unlike all other values...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   722
   *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   723
   * u16_v(query[string_length]) = mb_hton(temp_crc);  -> This is wrong !!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   724
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   725
  /* NOTE: We have already checked above that RTU_FRAME_CRC_LENGTH is >= 2 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   726
  u16 crc = crc_calc(buf, cnt);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   727
  buf[cnt]   = lsb(crc);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   728
  buf[cnt+1] = msb(crc);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   729
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   730
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   731
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   732
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   733
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   734
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   735
/**     A slow version of the      **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   736
/**          CRC function          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   737
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   738
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   739
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   740
/* crc optimized for smallest memory footprint */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   741
static u16 crc_slow(u8 *buf, int cnt)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   742
{
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   743
  int bit;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   744
  u16 temp,flag;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   745
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   746
  temp=0xFFFF;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   747
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   748
  while (cnt-- != 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   749
    temp=temp ^ *buf++;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   750
    for (bit=1; bit<=8; bit++) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   751
      flag = temp & 0x0001;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   752
      /* NOTE:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   753
       *  - since temp is unsigned, we are guaranteed a zero in MSbit;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   754
       *  - if it were signed, the value placed in the MSbit would be
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   755
       *      compiler dependent!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   756
       */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   757
      temp >>= 1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   758
      if (flag)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   759
        temp=temp ^ 0xA001;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   760
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   761
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   762
  return(temp);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   763
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   764
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   765
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   766
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   767
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   768
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   769
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   770
/**     A fast version of the      **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   771
/**          CRC function          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   772
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   773
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   774
static u8 *crc_fast_buf = NULL;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   775
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   776
/* crc optimized for speed */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   777
static u16 crc_fast(u8 *buf, int cnt)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   778
{
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   779
/* NOTE: The following arrays have been replaced by an equivalent
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   780
 *      array (crc_fast_buf[]) initialised at run-time.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   781
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   782
/*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   783
  static u8 buf_lsb[] = {0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   784
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   785
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   786
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   787
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   788
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   789
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   790
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   791
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   792
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   793
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   794
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   795
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   796
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   797
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   798
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   799
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   800
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   801
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   802
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   803
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   804
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   805
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   806
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   807
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   808
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   809
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   810
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   811
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   812
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   813
                         0x00, 0xc1, 0x81, 0x40, 0x01, 0xc0, 0x80, 0x41,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   814
                         0x01, 0xc0, 0x80, 0x41, 0x00, 0xc1, 0x81, 0x40
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   815
                        };
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   816
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   817
  static u8 buf_msb[] = {0x00, 0xc0, 0xc1, 0x01, 0xc3, 0x03, 0x02, 0xc2,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   818
                         0xc6, 0x06, 0x07, 0xc7, 0x05, 0xc5, 0xc4, 0x04,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   819
                         0xcc, 0x0c, 0x0d, 0xcd, 0x0f, 0xcf, 0xce, 0x0e,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   820
                         0x0a, 0xca, 0xcb, 0x0b, 0xc9, 0x09, 0x08, 0xc8,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   821
                         0xd8, 0x18, 0x19, 0xd9, 0x1b, 0xdb, 0xda, 0x1a,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   822
                         0x1e, 0xde, 0xdf, 0x1f, 0xdd, 0x1d, 0x1c, 0xdc,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   823
                         0x14, 0xd4, 0xd5, 0x15, 0xd7, 0x17, 0x16, 0xd6,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   824
                         0xd2, 0x12, 0x13, 0xd3, 0x11, 0xd1, 0xd0, 0x10,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   825
                         0xf0, 0x30, 0x31, 0xf1, 0x33, 0xf3, 0xf2, 0x32,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   826
                         0x36, 0xf6, 0xf7, 0x37, 0xf5, 0x35, 0x34, 0xf4,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   827
                         0x3c, 0xfc, 0xfd, 0x3d, 0xff, 0x3f, 0x3e, 0xfe,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   828
                         0xfa, 0x3a, 0x3b, 0xfb, 0x39, 0xf9, 0xf8, 0x38,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   829
                         0x28, 0xe8, 0xe9, 0x29, 0xeb, 0x2b, 0x2a, 0xea,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   830
                         0xee, 0x2e, 0x2f, 0xef, 0x2d, 0xed, 0xec, 0x2c,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   831
                         0xe4, 0x24, 0x25, 0xe5, 0x27, 0xe7, 0xe6, 0x26,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   832
                         0x22, 0xe2, 0xe3, 0x23, 0xe1, 0x21, 0x20, 0xe0,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   833
                         0xa0, 0x60, 0x61, 0xa1, 0x63, 0xa3, 0xa2, 0x62,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   834
                         0x66, 0xa6, 0xa7, 0x67, 0xa5, 0x65, 0x64, 0xa4,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   835
                         0x6c, 0xac, 0xad, 0x6d, 0xaf, 0x6f, 0x6e, 0xae,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   836
                         0xaa, 0x6a, 0x6b, 0xab, 0x69, 0xa9, 0xa8, 0x68,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   837
                         0x78, 0xb8, 0xb9, 0x79, 0xbb, 0x7b, 0x7a, 0xba,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   838
                         0xbe, 0x7e, 0x7f, 0xbf, 0x7d, 0xbd, 0xbc, 0x7c,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   839
                         0xb4, 0x74, 0x75, 0xb5, 0x77, 0xb7, 0xb6, 0x76,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   840
                         0x72, 0xb2, 0xb3, 0x73, 0xb1, 0x71, 0x70, 0xb0,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   841
                         0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   842
                         0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   843
                         0x9c, 0x5c, 0x5d, 0x9d, 0x5f, 0x9f, 0x9e, 0x5e,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   844
                         0x5a, 0x9a, 0x9b, 0x5b, 0x99, 0x59, 0x58, 0x98,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   845
                         0x88, 0x48, 0x49, 0x89, 0x4b, 0x8b, 0x8a, 0x4a,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   846
                         0x4e, 0x8e, 0x8f, 0x4f, 0x8d, 0x4d, 0x4c, 0x8c,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   847
                         0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   848
                         0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   849
                        };
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   850
*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   851
  u8 crc_msb = 0xFF;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   852
  u8 crc_lsb = 0xFF;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   853
  int index;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   854
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   855
  if (cnt <= 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   856
    fprintf(stderr, "\nInternal program error in file %s at line %d\n\n\n", __FILE__, __LINE__);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   857
    exit(EXIT_FAILURE);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   858
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   859
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   860
  while (cnt-- != 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   861
    index = 2 * (crc_lsb ^ *buf++);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   862
    crc_lsb = crc_msb ^ crc_fast_buf[index]/* buf_lsb[index/2] */;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   863
    crc_msb = crc_fast_buf[index + 1] /* buf_msb[index/2] */;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   864
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   865
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   866
  return crc_msb*0x0100 + crc_lsb;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   867
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   868
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   869
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   870
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   871
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   872
/**  init() and done() functions   **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   873
/**      of fast CRC version       **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   874
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   875
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   876
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   877
static inline int crc_fast_init(void) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   878
  int i;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   879
  u8  data[2];
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   880
  u16 tmp_crc;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   881
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   882
  if ((crc_fast_buf = (u8 *)malloc(256 * 2)) == NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   883
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   884
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   885
  for (i = 0x00; i < 0x100; i++) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   886
    data[0] = 0xFF;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   887
    data[1] = i;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   888
    data[1] = ~data[1];
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   889
    tmp_crc = crc_slow(data, 2);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   890
    crc_fast_buf[2*i    ] = lsb(tmp_crc);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   891
    crc_fast_buf[2*i + 1] = msb(tmp_crc);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   892
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   893
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   894
  return 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   895
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   896
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   897
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   898
static inline void crc_fast_done(void) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   899
  free(crc_fast_buf);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   900
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   901
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   902
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   903
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   904
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   905
/**  init() and done() functions   **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   906
/**         of generic CRC         **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   907
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   908
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   909
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   910
static inline int crc_init(optimization_t opt) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   911
  switch (opt) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   912
    case optimize_speed:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   913
      if (crc_fast_init() < 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   914
        return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   915
      crc_calc = crc_fast;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   916
      return 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   917
    case optimize_size :
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   918
      crc_calc = crc_slow;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   919
      return 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   920
    default:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   921
      return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   922
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   923
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   924
  /* humour the compiler */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   925
  return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   926
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   927
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   928
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   929
static inline int crc_done(void) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   930
  if (crc_calc == crc_fast)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   931
    crc_fast_done();
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   932
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   933
  crc_calc = DEF_CRC_FUNCTION;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   934
  return 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   935
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   936
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   937
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   938
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   939
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   940
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   941
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   942
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   943
/****              Sending of Modbus RTU Frames            ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   944
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   945
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   946
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   947
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   948
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   949
/*  W A R N I N G
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   950
 *  =============
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   951
 *     The modbus_rtu_write() function assumes that the caller
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   952
 *     has allocated a few bytes extra for the buffer containing
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   953
 *     the data. These bytes will be used to write the crc.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   954
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   955
 *     The caller of this function MUST make sure that the data
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   956
 *     buffer, although only containing data_length bytes, has
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   957
 *     been allocated with a size equal to or larger than
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   958
 *     data_length + RTU_FRAME_CRC_LENGTH bytes
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   959
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   960
 *     I know, this is a very ugly hack, but we don't have much
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   961
 *     choice (please read other comments further on for more
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   962
 *     explanations)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   963
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   964
 *     We will nevertheless try and make this explicit by having the
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   965
 *     library initialisation function (modbus_rtu_init() ) return a
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   966
 *     value specifying how many extra bytes this buffer should have.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   967
 *     Maybe this way this very ugly hack won't go unnoticed, and we
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   968
 *     won't be having any segmentation faults...!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   969
 * 
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   970
 *     NOTE: for now the transmit_timeout is silently ignored in RTU version!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   971
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   972
int modbus_rtu_write(int    nd,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   973
                     u8    *data,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   974
                     size_t data_length,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   975
                     u16    transaction_id,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   976
                     const struct timespec *transmit_timeout
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   977
                    )
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   978
{
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   979
  fd_set rfds;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   980
  struct timeval timeout;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   981
  int res, send_retries;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   982
  nd_entry_t *nd_entry;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   983
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   984
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   985
  fprintf(stderr, "modbus_rtu_write(fd=%d) called...\n", nd);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   986
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   987
  /* check if nd is correct... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   988
  if ((nd_entry = nd_table_get_nd(&nd_table_, nd)) == NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   989
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   990
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   991
  /* check if nd is initialzed... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   992
  if (nd_entry->fd < 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   993
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   994
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   995
  /**************************
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   996
  * append crc to frame... *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   997
  **************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   998
/* WARNING:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
   999
 *     The crc_write() function assumes that we have an extra
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1000
 *     RTU_FRAME_CRC_LENGTH free bytes at the end of the *data
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1001
 *     buffer.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1002
 *     The caller of this function had better make sure he has
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1003
 *     allocated those extra bytes, or a segmentation fault will
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1004
 *     occur.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1005
 *     Please read on why we leave this as it is...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1006
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1007
 * REASONS:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1008
 *     We want to write the data and the crc in a single call to
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1009
 *     the OS. This is the only way we can minimally try to gurantee
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1010
 *     that we will not be introducing a silence of more than 1.5
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1011
 *     character transmission times between any two characters.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1012
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1013
 *     We could do the above using one of two methods:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1014
 *       (a) use a special writev() call in which the data
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1015
 *           to be sent is stored in two buffers (one for the
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1016
 *           data and the other for the crc).
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1017
 *       (b) place all the data in a single linear buffer and
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1018
 *           use the normal write() function.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1019
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1020
 *     We cannot use (a) since the writev(2) function does not seem
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1021
 *     to be POSIX compliant...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1022
 *     (b) has the drawback that we would need to allocate a new buffer,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1023
 *      and copy all the data into that buffer. We have enough copying of
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1024
 *      data between buffers as it is, so we won't be doing it here
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1025
 *      yet again!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1026
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1027
 *      The only option that seems left over is to have the caller
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1028
 *      of this function allocate a few extra bytes. Let's hope he
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1029
 *      does not forget!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1030
*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1031
  crc_write(data, data_length);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1032
  data_length += RTU_FRAME_CRC_LENGTH;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1033
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1034
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1035
/* Print the hex value of each character that is about to be
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1036
 * sent over the bus.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1037
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1038
  { int i;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1039
    for(i = 0; i < data_length; i++)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1040
      fprintf(stderr, "[0x%2X]", data[i]);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1041
    fprintf(stderr, "\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1042
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1043
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1044
   /* THE MAIN LOOP!!! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1045
  /* NOTE: The modbus standard specifies that the message must
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1046
   *       be sent continuosly over the wire with maximum
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1047
   *       inter-character delays of 1.5 character intervals.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1048
   *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1049
   *       If the write() call is interrupted by a signal, then
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1050
   *       this delay will most probably be exceeded. We should then
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1051
   *       re-start writing the query from the begining.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1052
   *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1053
   *       BUT, can we really expect the write() call to return
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1054
   *       query_length on every platform when no error occurs?
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1055
   *       The write call would still be correct if it only wrote
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1056
   *       1 byte at a time!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1057
   *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1058
   *       To protect ourselves getting into an infinte loop in the
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1059
   *       above cases, we specify a maximum number of retries, and
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1060
   *       hope for the best...! The worst will now be we simply do
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1061
   *       not get to send out a whole frame, and will therefore always
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1062
   *       fail on writing a modbus frame!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1063
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1064
  send_retries = RTU_FRAME_SEND_RETRY + 1; /* must try at least once... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1065
  while (send_retries > 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1066
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1067
    /*******************************
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1068
     * synchronise with the bus... *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1069
     *******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1070
    /* Remember that a RS485 bus is half-duplex, so we have to wait until
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1071
     * nobody is transmitting over the bus for our turn to transmit.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1072
     * This will never happen on a modbus network if the master and
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1073
     * slave state machines never get out of synch (granted, it probably
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1074
     * only has two states, but a state machine nonetheless), but we want
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1075
     * to make sure we can re-synchronise if they ever do get out of synch.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1076
     *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1077
     * The following lines will guarantee that we will re-synchronise our
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1078
     * state machine with the current state of the bus.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1079
     *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1080
     * We first wait until the bus has been silent for at least
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1081
     * char_interval_timeout (i.e. 3.5 character interval). We then flush
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1082
     * any input and output that might be on the cache.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1083
     */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1084
      /* NOTES:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1085
       *   - we do not need to reset the rfds with FD_SET(ttyfd, &rfds)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1086
       *     before every call to select! We only wait on one file descriptor,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1087
       *     so if select returns succesfully, it must have that same file
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1088
       *     decriptor set in the rdfs!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1089
       *     If select returns with a timeout, then we do not get to call
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1090
       *     select again!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1091
       *   -  On Linux, timeout (i.e. timeout) is modified by select() to
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1092
       *      reflect the amount of time not slept; most other implementations
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1093
       *      do not do this. In the cases in which timeout is not modified,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1094
       *      we will simply have to wait for longer periods if select is
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1095
       *      interrupted by a signal.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1096
       */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1097
    FD_ZERO(&rfds);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1098
    FD_SET(nd_entry->fd, &rfds);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1099
    timeout = nd_entry->time_35_char_;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1100
    while ((res = select(nd_entry->fd+1, &rfds, NULL, NULL, &timeout)) != 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1101
      if (res > 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1102
        /* we are receiving data over the serial port! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1103
        /* Throw the data away!                        */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1104
        tcflush(nd_entry->fd, TCIFLUSH); /* flush the input stream */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1105
        /* reset the timeout value! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1106
        timeout = nd_entry->time_35_char_;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1107
        /* We do not need to reset the FD SET here! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1108
      } else {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1109
        /* some kind of error ocurred */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1110
        if (errno != EINTR)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1111
          /* we were not interrupted by a signal */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1112
          return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1113
        /* We will be calling select() again.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1114
         * We need to reset the FD SET !
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1115
         */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1116
        FD_ZERO(&rfds);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1117
        FD_SET(nd_entry->fd, &rfds);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1118
      }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1119
    } /* while (select()) */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1120
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1121
    /* Flush both input and output streams... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1122
    /* NOTE: Due to the nature of the modbus protocol,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1123
     *       when a frame is sent all previous
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1124
     *       frames that may have arrived at the sending node become
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1125
     *       irrelevant.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1126
     */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1127
    tcflush(nd_entry->fd, TCIOFLUSH);       /* flush the input & output streams */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1128
    recv_buf_reset(&nd_entry->recv_buf_);   /* reset the recv buffer            */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1129
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1130
    /**********************
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1131
     * write to output... *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1132
     **********************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1133
     /* Please see the comment just above the main loop!! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1134
    if ((res = write(nd_entry->fd, data, data_length)) != data_length) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1135
      if ((res < 0) && (errno != EAGAIN ) && (errno != EINTR ))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1136
        return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1137
    } else {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1138
      /* query succesfully sent! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1139
      /* res == query_length     */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1140
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1141
      /*  NOTE: We do not flush the input stream after sending the frame!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1142
       *        If the process gets swapped out between the end of writing
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1143
       *        to the serial port, and the call to flush the input of the
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1144
       *        same serial port, the response to the modbus query may be
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1145
       *        sent over between those two calls. This would result in the
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1146
       *        tcflush(ttyfd, TCIFLUSH) call flushing out the response
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1147
       *        to the query we have just sent!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1148
       *        Not a good thing at all... ;-)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1149
       */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1150
      return data_length - RTU_FRAME_CRC_LENGTH;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1151
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1152
    /* NOTE: The maximum inter-character delay of 1.5 character times
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1153
     *       has most probably been exceeded, so we abort the frame and
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1154
     *       retry again...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1155
     */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1156
    send_retries--;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1157
  } /* while()  MAIN LOOP */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1158
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1159
   /* maximum retries exceeded */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1160
  return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1161
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1162
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1163
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1164
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1165
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1166
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1167
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1168
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1169
/****              Receiving Modbus RTU Frames             ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1170
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1171
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1172
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1173
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1174
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1175
#if     MIN_FRAME_LENGTH < 2
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1176
#error  Modbus RTU frames have a minimum length larger than MIN_FRAME_LENGTH.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1177
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1178
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1179
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1180
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1181
/**     Guess length of frame      **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1182
/**         being read.            **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1183
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1184
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1185
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1186
/*  Auxiliary function to the search_for_frame() function.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1187
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1188
 *  NOTE: data_byte_count must be >=2 for correct operation, therefore
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1189
 *        the #error condition above.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1190
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1191
 *  Function to determine the length of the frame currently being read,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1192
 *  assuming it is a query/response frame.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1193
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1194
 *  The guess is obtained by analysing the bytes that have already been
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1195
 *  read. Sometimes we cannot be sure what is the frame length, because
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1196
 *  not enough bytes of the frame have been read yet (for example, frames
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1197
 *  that have a byte_count value which has not yet been read). In these
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1198
 *  cases we return not the frame length, but an error (-1).
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1199
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1200
 *  If we find the data does not make any sense (i.e. it cannot be a valid
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1201
 *  modbus frame), we return -1.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1202
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1203
static int frame_length(u8 *frame_data,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1204
                        int frame_data_length,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1205
                          /* The array containing the lengths of frames. */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1206
                          /*   - query_frame_length[]
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1207
                           *   - response_frame_length[]
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1208
                           */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1209
                        i8  *frame_length_array) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1210
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1211
  u8  function_code;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1212
  int res;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1213
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1214
   /* check consistency of input parameters... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1215
 /*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1216
  if ((frame_data == NULL) || (frame_length_array == NULL) || (frame_data_length < 2))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1217
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1218
  */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1219
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1220
  function_code = frame_data[L2_FRAME_FUNCTION_OFS];
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1221
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1222
   /* hard code the length of response to diagnostic function 8 (0x08), with
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1223
    * subfunction 21 (0x15), and sub-sub-function (a.k.a. operation) 3 (0x03),
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1224
    * which contains a byte count...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1225
    */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1226
  if ((function_code == 0x08) && (frame_length_array == response_frame_lengths)) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1227
    if (frame_data_length < 4) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1228
      /* not enough info to determine the sub-function... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1229
      return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1230
    } else {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1231
      if ((frame_data[2] == 0x00) && (frame_data[3] == 0x15)) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1232
        /* we need a couple more bytes to figure out the sub-sub-function... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1233
        if (frame_data_length < 6) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1234
          /* not enough info to determine the sub-sub-function... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1235
          return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1236
        } else {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1237
          if ((frame_data[4] == 0x00) && (frame_data[5] == 0x03)) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1238
            /* We have found a response frame to diagnostic sub-function ... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1239
            if (frame_data_length < 8) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1240
              /* not enough info to determine the frame length */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1241
              return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1242
            } else {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1243
              return /*HEADER*/ 6 + mb_ntoh(u16_v(frame_data[6])) + RTU_FRAME_CRC_LENGTH;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1244
            }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1245
          }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1246
        }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1247
      }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1248
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1249
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1250
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1251
  res = frame_length_array[function_code];
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1252
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1253
  switch(res) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1254
    case BYTE_COUNT_3 :
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1255
      if (frame_data_length >= 3)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1256
        return BYTE_COUNT_3_HEADER  + frame_data[2] + RTU_FRAME_CRC_LENGTH;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1257
      break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1258
    case BYTE_COUNT_34:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1259
      if (frame_data_length >= 4)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1260
        return BYTE_COUNT_34_HEADER + mb_ntoh(u16_v(frame_data[2])) + RTU_FRAME_CRC_LENGTH;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1261
      break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1262
    case BYTE_COUNT_7 :
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1263
      if (frame_data_length >= 7)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1264
        return BYTE_COUNT_7_HEADER  + frame_data[6] + RTU_FRAME_CRC_LENGTH;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1265
      break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1266
    case BYTE_COUNT_11:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1267
      if (frame_data_length >= 11)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1268
        return BYTE_COUNT_11_HEADER + frame_data[10] + RTU_FRAME_CRC_LENGTH;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1269
      break;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1270
    case BYTE_COUNT_U :
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1271
      return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1272
    default:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1273
      return res + RTU_FRAME_CRC_LENGTH;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1274
  } /* switch() */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1275
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1276
  /* unknown frame length */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1277
  return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1278
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1279
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1280
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1281
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1282
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1283
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1284
/**      Search for a frame        **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1285
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1286
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1287
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1288
/* Search for a valid frame in the current data.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1289
 * If no valid frame is found, then we return -1.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1290
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1291
 * NOTE: Since frame verification is done by calculating the CRC, which is rather
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1292
 *       CPU intensive, and this function may be called several times with the same,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1293
 *       data, we keep state regarding the result of previous invocations...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1294
 *       That is the reason for the *search_history parameter!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1295
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1296
static int search_for_frame(u8 *frame_data,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1297
                            int frame_data_length,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1298
                            int *search_history) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1299
  int query_length, resp_length;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1300
  u8  function_code;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1301
    /* *search_history flag will have or'ed of following values... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1302
#define SFF_HIST_NO_QUERY_FRAME     0x01
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1303
#define SFF_HIST_NO_RESPONSE_FRAME  0x02
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1304
#define SFF_HIST_NO_FRAME  (SFF_HIST_NO_RESPONSE_FRAME + SFF_HIST_NO_QUERY_FRAME)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1305
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1306
  if ((*search_history == SFF_HIST_NO_FRAME) ||
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1307
      (frame_data_length < MIN_FRAME_LENGTH) ||
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1308
      (frame_data_length > MAX_RTU_FRAME_LENGTH))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1309
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1310
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1311
  function_code = frame_data[L2_FRAME_FUNCTION_OFS];
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1312
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1313
  /* check for exception frame... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1314
  if ((function_code && 0x80) == 0x80) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1315
    if (frame_data_length >= EXCEPTION_FRAME_LENGTH + RTU_FRAME_CRC_LENGTH) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1316
      /* let's check CRC for valid frame. */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1317
      if (   crc_calc(frame_data, EXCEPTION_FRAME_LENGTH)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1318
          == crc_read(frame_data, EXCEPTION_FRAME_LENGTH))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1319
        return EXCEPTION_FRAME_LENGTH + RTU_FRAME_CRC_LENGTH;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1320
      else
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1321
        /* We have checked the CRC, and it is not a valid frame! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1322
        *search_history |= SFF_HIST_NO_FRAME;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1323
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1324
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1325
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1326
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1327
  /* check for valid function code */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1328
  if ((function_code > MAX_FUNCTION_CODE) || (function_code < 1)) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1329
    /* This is an invalid frame!!! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1330
    *search_history |= SFF_HIST_NO_FRAME;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1331
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1332
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1333
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1334
  /* let's guess the frame length */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1335
  query_length = resp_length = -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1336
  if ((*search_history & SFF_HIST_NO_QUERY_FRAME) == 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1337
    query_length = frame_length(frame_data, frame_data_length, query_frame_lengths);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1338
  if ((*search_history & SFF_HIST_NO_RESPONSE_FRAME) == 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1339
    resp_length  = frame_length(frame_data, frame_data_length, response_frame_lengths);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1340
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1341
  /* let's check whether any of the lengths are valid...*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1342
  /* If any of the guesses coincides with the available data length
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1343
   * we check that length first...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1344
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1345
  if ((frame_data_length == query_length) || (frame_data_length == resp_length)) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1346
    if (   crc_calc(frame_data, frame_data_length - RTU_FRAME_CRC_LENGTH)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1347
        == crc_read(frame_data, frame_data_length - RTU_FRAME_CRC_LENGTH))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1348
      return frame_data_length;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1349
    /* nope, wrong guess...*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1350
    if (frame_data_length == query_length)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1351
      *search_history |= SFF_HIST_NO_QUERY_FRAME;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1352
    if (frame_data_length == resp_length)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1353
      *search_history |= SFF_HIST_NO_RESPONSE_FRAME;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1354
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1355
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1356
  /* let's shoot for a query frame */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1357
  if ((*search_history & SFF_HIST_NO_QUERY_FRAME) == 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1358
    if (query_length >= 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1359
      if (frame_data_length >= query_length) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1360
        /* let's check if we have a valid frame */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1361
        if (   crc_calc(frame_data, query_length - RTU_FRAME_CRC_LENGTH)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1362
            == crc_read(frame_data, query_length - RTU_FRAME_CRC_LENGTH))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1363
          return query_length;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1364
        else
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1365
          /* We have checked the CRC, and it is not a valid frame! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1366
          *search_history |= SFF_HIST_NO_QUERY_FRAME;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1367
      }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1368
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1369
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1370
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1371
  /* let's shoot for a response frame */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1372
  if ((*search_history & SFF_HIST_NO_RESPONSE_FRAME) == 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1373
    if (resp_length >= 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1374
      if (frame_data_length >= resp_length) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1375
        /* let's check if we have a valid frame */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1376
        if (   crc_calc(frame_data, resp_length - RTU_FRAME_CRC_LENGTH)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1377
            == crc_read(frame_data, resp_length - RTU_FRAME_CRC_LENGTH))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1378
          return resp_length;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1379
        else
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1380
          *search_history |= SFF_HIST_NO_RESPONSE_FRAME;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1381
      }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1382
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1383
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1384
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1385
  /* Could not find valid frame... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1386
  return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1387
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1388
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1389
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1390
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1391
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1392
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1393
/**          Read a frame          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1394
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1395
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1396
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1397
/* A small auxiliary function, just to make the code easier to read... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1398
static inline void next_frame_offset(recv_buf_t *buf, u8 *slave_id) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1399
  buf->frame_search_history = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1400
  lb_data_purge(&(buf->data_buf), 1 /* skip one byte */);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1401
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1402
  if (slave_id == NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1403
    return;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1404
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1405
  /* keep ignoring bytes, until we find one == *slave_id,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1406
   * or no more bytes...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1407
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1408
  while (lb_data_count(&(buf->data_buf)) != 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1409
    if (*lb_data(&(buf->data_buf)) == *slave_id)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1410
      return;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1411
    lb_data_purge(&(buf->data_buf), 1 /* skip one byte */);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1412
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1413
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1414
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1415
/* A small auxiliary function, just to make the code easier to read... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1416
static inline int return_frame(recv_buf_t *buf,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1417
                               int frame_length,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1418
                               u8 **recv_data_ptr) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1419
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1420
  fprintf(stderr, "\n" );
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1421
  fprintf(stderr, "returning valid frame of %d bytes.\n", frame_length);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1422
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1423
    /* set the data pointer */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1424
  *recv_data_ptr = lb_data(&(buf->data_buf));
15
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1425
    /* Mark the frame bytes to be deleted off the buffer by the next call to lb_data_purge() */
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1426
	/* Notice that we cannot delete the frame bytes right away, as they will still be accessed by whoever
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1427
	 * called read_frame(). We can only delete this data on the next call to read_frame() 
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1428
	 */
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1429
  lb_data_mark_for_purge(&(buf->data_buf), frame_length);
0
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1430
    /* reset the search_history flag */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1431
  buf->frame_search_history = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1432
    /* if the buffer becomes empty, then reset boundary flag */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1433
  if (lb_data_count(&(buf->data_buf)) <= 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1434
    buf->found_frame_boundary = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1435
    /* return the frame length, excluding CRC */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1436
  return frame_length - RTU_FRAME_CRC_LENGTH;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1437
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1438
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1439
/* A function to read a valid frame off the rtu bus.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1440
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1441
 * NOTES:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1442
 *        - The returned frame is guaranteed to be a valid frame.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1443
 *        - The returned length does *not* include the CRC.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1444
 *        - The returned frame is not guaranteed to have the same
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1445
 *          slave id as that stored in (*slave_id). This value is used
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1446
 *          merely in optimizing the search for wanted valid frames
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1447
 *          after reading an aborted frame. Only in this situation do
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1448
 *          we limit our search for frames with a slvae id == (*slave_id).
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1449
 *          Under normal circumstances, the value in (*slave_id) is
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1450
 *          simply ignored...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1451
 *          If any valid frame is desired, then slave_id should be NULL.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1452
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1453
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1454
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1455
/* NOTE: We cannot relly on the 3.5 character interval between frames to detect
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1456
 *       end of frame. We are reading the bytes from a user process, so in
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1457
 *       essence the bytes we are reading are coming off a cache.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1458
 *       Any inter-character delays between the arrival of the bytes are
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1459
 *       lost as soon as they were placed in the cache.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1460
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1461
 *       Our only recourse is to analyse the frame we are reading in real-time,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1462
 *       and check if it is a valid frame by checking it's CRC.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1463
 *       To optimise this, we must be able to figure out the length
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1464
 *       of the frame currently being received by analysing the first bytes
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1465
 *       of that frame. Unfortunately, we have three problems with this:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1466
 *         1) The spec does not specify the format of every possible modbus
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1467
 *            frame. For ex.functions 9, 10, 13, 14, 18 and 19(?).
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1468
 *         2) It is not possible to figure out whether a frame is a query
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1469
 *            or a response by just analysing the frame, and query and response
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1470
 *            frames have different sizes...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1471
 *         3) A frame may be aborted in the middle! We have no easy way of telling
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1472
 *            if what we are reading is a partial (aborted) frame, followed by a
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1473
 *            correct frame.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1474
 *       Possible solutions to:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1475
 *         1) We could try to reverse engineer, but at the moment I have no
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1476
 *            PLCs that will generate the required frames.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1477
 *            The chosen method is to verify the CRC if we are lucky enough to
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1478
 *            detect the 3.5 frame boundary imediately following one of these
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1479
 *            frames of unknown length.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1480
 *            If we do not detect any frame boundary, then our only option
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1481
 *            is to consider it an aborted frame.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1482
 *         2) We aim for the query frame (usually the shortest), and check
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1483
 *            it's CRC. If it matches, we accept, the frame, otherwise we try
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1484
 *            a response frame.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1485
 *         3) The only way is to consider a frame boundary after each byte,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1486
 *            (i.e. ignore one bye at a time) and verify if the following bytes
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1487
 *            constitue a valid frame (by checking the CRC).
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1488
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1489
 *       When reading an aborted frame followed by two or more valid frames, if
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1490
 *       we are unlucky and do not detetect any frame boundary using the 3.5
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1491
 *       character interval, then we will most likely be reading in bytes
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1492
 *       beyond the first valid frame. This means we will have to store the extra
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1493
 *       bytes we have already read, so they may be handled the next time the
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1494
 *       read_frame() function is called.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1495
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1496
 /*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1497
  * NOTE: The modbus RTU spec is inconsistent on how to handle
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1498
  *       inter-character delays larger than 1.5 characters.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1499
  *       - On one paragraph it is stated that any delay larger than
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1500
  *         1.5 character times aborts the current frame, and a new
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1501
  *         frame is started.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1502
  *       - On another paragraph it is stated that a frame must begin
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1503
  *         with a silence of 3.5 character times.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1504
  *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1505
  * We will therefore consider that any delay larger than 1.5 character
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1506
  * times terminates a valid frame. All the above references to the 3.5 character
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1507
  * interval should therefore be read as a 1.5 character interval.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1508
  */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1509
/* NOTE: This function is only called from one place in the rest of the code,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1510
 * so we might just as well make it inline...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1511
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1512
/* RETURNS: number of bytes in received frame
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1513
 *          -1 on read file error
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1514
 *          -2 on timeout
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1515
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1516
static inline int read_frame(nd_entry_t *nd_entry,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1517
                             u8 **recv_data_ptr,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1518
                             struct timespec *end_time,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1519
                             u8 *slave_id)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1520
{
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1521
  /* temporary variables... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1522
  fd_set rfds;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1523
  struct timeval timeout;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1524
  int res, read_stat;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1525
  int frame_length;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1526
  recv_buf_t *recv_buf = &nd_entry->recv_buf_;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1527
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1528
    /* Flag:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1529
     *       1 => we are reading in an aborted frame, so we must
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1530
     *            start ignoring bytes...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1531
     */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1532
  int found_aborted_frame;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1533
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1534
  /* assume error... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1535
  *recv_data_ptr = NULL;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1536
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1537
  /*===================================*
15
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1538
   * Delete any previously received data that has already been returned as a valid frame in *
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1539
   *===================================*/  
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1540
   /* Delete any previously received data that has already been returned as a valid frame in 
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1541
    * the previous invocation of read_frame().
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1542
	* Notice that the data that will be deleted hass ben marked for deletion by calling
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1543
	* lb_data_mark_for_purge() in return_frame()
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1544
	*/
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1545
  lb_data_purge(&(recv_buf->data_buf), 0);
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1546
cadd89d14ca5 fix bug: frame data read from network was potentially being moved inside buffer (lb_normalize()) before it was processed by caller to read_frame()
mjsousa <msousa@fe.up.pt>
parents: 0
diff changeset
  1547
  /*===================================*
0
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1548
   * Check for frame in left over data *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1549
   *===================================*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1550
  /* If we have any data left over from previous call to read_frame()
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1551
   * (i.e. this very same function), then we try to interpret that
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1552
   * data, and do not wait for any extra bytes...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1553
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1554
  frame_length = search_for_frame(lb_data(&recv_buf->data_buf),
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1555
                                  lb_data_count(&recv_buf->data_buf),
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1556
                                  &recv_buf->frame_search_history);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1557
  if (frame_length > 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1558
    /* We found a valid frame! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1559
    return return_frame(recv_buf, frame_length, recv_data_ptr);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1560
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1561
  /* If the left over data finished at a frame boundary, and since it
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1562
   * doesn't contain any valid frame, we discard those bytes...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1563
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1564
  if (recv_buf->found_frame_boundary == 1)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1565
    recv_buf_reset(recv_buf);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1566
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1567
  /*============================*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1568
   * wait for data availability *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1569
   *============================*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1570
  /* if we can't find a valid frame in the existing data, or no data
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1571
   * was left over, then we need to read more bytes!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1572
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1573
    FD_ZERO(&rfds);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1574
    FD_SET(nd_entry->fd, &rfds);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1575
    {int sel_res = my_select(nd_entry->fd + 1, &rfds, NULL, end_time);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1576
      if (sel_res < 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1577
        return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1578
      if (sel_res == 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1579
        return -2;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1580
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1581
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1582
  /*==============*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1583
   * read a frame *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1584
   *==============*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1585
  /* The main loop that reads one frame               */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1586
  /*  (multiple calls to read() )                     */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1587
  /* and jumps out as soon as it finds a valid frame. */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1588
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1589
  found_aborted_frame = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1590
  FD_ZERO(&rfds);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1591
  FD_SET(nd_entry->fd, &rfds);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1592
  while (1) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1593
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1594
    /*------------------*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1595
     * read frame bytes *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1596
     *------------------*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1597
     /* Read in as many bytes as possible...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1598
      * But only if we have not found a frame boundary. Once we find
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1599
      *  a frame boundary, we do not want to read in any more bytes
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1600
      *  and mix them up with the current frame's bytes.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1601
      */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1602
    if (recv_buf->found_frame_boundary == 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1603
      read_stat = read(nd_entry->fd,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1604
                       lb_free(&recv_buf->data_buf),
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1605
                       lb_free_count(&recv_buf->data_buf));
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1606
      if (read_stat < 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1607
        if (errno != EINTR)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1608
          return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1609
        else
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1610
          read_stat = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1611
      }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1612
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1613
      {/* display the hex code of each character received */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1614
        int i;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1615
        fprintf(stderr, "-");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1616
        for (i=0; i < read_stat; i++)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1617
          fprintf(stderr, "<0x%2X>", *(lb_free(&recv_buf->data_buf) + i));
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1618
      }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1619
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1620
      lb_data_add(&recv_buf->data_buf, read_stat);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1621
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1622
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1623
    /*-----------------------*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1624
     * check for valid frame *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1625
     *-----------------------*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1626
    frame_length = search_for_frame(lb_data(&recv_buf->data_buf),
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1627
                                    lb_data_count(&recv_buf->data_buf),
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1628
                                    &recv_buf->frame_search_history);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1629
    if (frame_length > 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1630
      /* We found a valid frame! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1631
      return return_frame(recv_buf, frame_length, recv_data_ptr);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1632
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1633
    /* if we reach this point, we are sure we do not have valid frame
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1634
     * of known length in the current data with the current offset...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1635
     */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1636
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1637
    /*---------------------------------*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1638
     * Have we found an aborted frame? *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1639
     *---------------------------------*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1640
    if (lb_data_count(&recv_buf->data_buf) >= MAX_RTU_FRAME_LENGTH)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1641
      found_aborted_frame = 1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1642
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1643
    /*---------------------------------*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1644
     * Must we try a new frame_offset? *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1645
     *---------------------------------*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1646
    if (found_aborted_frame == 1) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1647
      /* Note that the found_aborted_frame flag is only set if:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1648
       *   1 - we have previously detected a frame_boundary,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1649
       *       (i.e. found_frame_boundary is == 1 !!) so we won't be
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1650
       *       reading in more bytes;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1651
       *   2 - we have read more bytes than the maximum frame length
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1652
       *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1653
       * Considering we have just failed finding a valid frame, and the above
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1654
       * points (1) and (2), then there is no way we are still going to
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1655
       * find a valid frame in the current data.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1656
       * We must therefore try a new first byte for the frame...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1657
       */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1658
      next_frame_offset(recv_buf, slave_id);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1659
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1660
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1661
    /*-----------------------------*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1662
     * check for data availability *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1663
     *-----------------------------*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1664
    if (recv_buf->found_frame_boundary == 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1665
      /* We need more bytes!! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1666
      /*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1667
       * if no character at the buffer, then we wait time_15_char_
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1668
       * before accepting end of frame
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1669
       */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1670
      /* NOTES:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1671
       *   - On Linux, timeout is modified by select() to reflect
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1672
       *     the amount of time not slept; most other implementations do
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1673
       *     not do this. On those platforms we will simply have to wait
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1674
       *     longer than we wished if select() is by any chance interrupted
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1675
       *     by a signal...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1676
       */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1677
      timeout = nd_entry->time_15_char_;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1678
      while ((res = select(nd_entry->fd+1, &rfds, NULL, NULL, &timeout)) < 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1679
        if (errno != EINTR)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1680
          return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1681
        /* We will be calling select() again.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1682
         * We need to reset the FD SET !
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1683
         */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1684
        FD_ZERO(&rfds);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1685
        FD_SET(nd_entry->fd, &rfds);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1686
      }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1687
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1688
      if (res == 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1689
        int frame_length = lb_data_count(&recv_buf->data_buf);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1690
        /* We have detected an end of frame using timing boundaries... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1691
        recv_buf->found_frame_boundary = 1; /* => stop trying to read any more bytes! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1692
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1693
        /* Let's check if we happen to have a correct frame... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1694
        if ((frame_length <= MAX_RTU_FRAME_LENGTH) &&
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1695
	    (frame_length - RTU_FRAME_CRC_LENGTH > 0)) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1696
          if (   crc_calc(lb_data(&recv_buf->data_buf), frame_length - RTU_FRAME_CRC_LENGTH)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1697
              == crc_read(lb_data(&recv_buf->data_buf), frame_length - RTU_FRAME_CRC_LENGTH)) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1698
            /* We have found a valid frame. Let's get out of here! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1699
            return return_frame(recv_buf, frame_length, recv_data_ptr);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1700
          }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1701
	}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1702
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1703
        /* We have detected a frame boundary, but the frame we read
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1704
         * is not valid...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1705
         *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1706
         * One of the following reasons must be the cause:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1707
         *   1 - we are reading a single aborted frame.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1708
         *   2 - we are reading more than one frame. The first frame,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1709
         *       followed by any number of valid and/or aborted frames,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1710
         *       may be one of:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1711
         *       a - a valid frame whose length is unknown to us,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1712
         *           i.e. it is not specified in the public Modbus spec.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1713
         *       b - an aborted frame.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1714
         *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1715
         * Due to the complexity of reading 2a as a correct frame, we will
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1716
         * consider it as an aborted frame. (NOTE: it is possible, but
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1717
         * we will ignore it until the need arises... hopefully, never!)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1718
         *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1719
         * To put it succintly, what wee now have is an 'aborted' frame
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1720
         * followed by one or more aborted and/or valid frames. To get to
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1721
         * any valid frames, and since we do not know where they begin,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1722
         * we will have to consider every byte as the possible begining
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1723
         * of a valid frame. For this permutation, we ignore the first byte,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1724
         * and carry on from there...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1725
         */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1726
        found_aborted_frame = 1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1727
        lb_data_purge(&recv_buf->data_buf, 1 /* skip one byte */);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1728
        recv_buf->frame_search_history = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1729
      }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1730
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1731
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1732
    /*-------------------------------*
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1733
     * check for data yet to process *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1734
     *-------------------------------*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1735
    if ((lb_data_count(&recv_buf->data_buf) < MIN_FRAME_LENGTH) &&
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1736
        (recv_buf->found_frame_boundary == 1)) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1737
      /* We have no more data to process, and will not read anymore! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1738
      recv_buf_reset(recv_buf);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1739
      /* Return TIMEOUT error */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1740
      return -2;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1741
    }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1742
  } /* while (1)*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1743
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1744
  /* humour the compiler... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1745
  return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1746
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1747
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1748
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1749
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1750
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1751
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1752
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1753
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1754
/**    Read a Modbus RTU frame     **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1755
/**                                **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1756
/************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1757
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1758
/* The public function that reads a valid modbus frame.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1759
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1760
 * The returned frame is guaranteed to be different to the
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1761
 * the frame stored in send_data, and to start with the
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1762
 * same slave address stored in send_data[0].
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1763
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1764
 * If send_data is NULL, send_data_length = 0, or
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1765
 * ignore_echo == 0, then the first valid frame read off
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1766
 * the bus is returned.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1767
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1768
 * return value: The length (in bytes) of the valid frame,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1769
 *               -1 on error
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1770
 *               -2 on timeout
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1771
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1772
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1773
int modbus_rtu_read(int *nd,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1774
                    u8 **recv_data_ptr,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1775
                    u16 *transaction_id,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1776
                    const u8 *send_data,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1777
                    int send_length,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1778
                    const struct timespec *recv_timeout) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1779
  struct timespec end_time, *ts_ptr;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1780
  int res, recv_length, iter;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1781
  u8 *local_recv_data_ptr;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1782
  u8 *slave_id, local_slave_id;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1783
  nd_entry_t *nd_entry;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1784
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1785
  /* Check input parameters... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1786
  if (nd == NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1787
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1788
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1789
  if (recv_data_ptr == NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1790
    recv_data_ptr = &local_recv_data_ptr;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1791
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1792
  if ((send_data == NULL) && (send_length != 0))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1793
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1794
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1795
  /* check if nd is correct... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1796
  if ((nd_entry = nd_table_get_nd(&nd_table_, *nd)) == NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1797
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1798
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1799
  /* check if nd is initialzed... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1800
  if (nd_entry->fd < 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1801
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1802
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1803
  slave_id = NULL;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1804
  if (send_length > L2_FRAME_SLAVEID_OFS) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1805
    local_slave_id = send_data[L2_FRAME_SLAVEID_OFS];
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1806
    slave_id = &local_slave_id;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1807
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1808
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1809
  /* We will potentially read many frames, and we cannot reset the timeout
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1810
   * for every frame we read. We therefore determine the absolute time_out,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1811
   * and use this as a parameter for each call to read_frame() instead of
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1812
   * using a relative timeout.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1813
   *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1814
   * NOTE: see also the timeout related comment in the read_frame()= function!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1815
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1816
  /* get the current time... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1817
  ts_ptr = NULL;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1818
  if (recv_timeout != NULL) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1819
     ts_ptr = &end_time;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1820
    *ts_ptr = timespec_add_curtime(*recv_timeout);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1821
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1822
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1823
  /* NOTE: When using a half-duplex RS-485 bus, some (most ?) RS232-485
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1824
   *       converters will send back to the RS232 port whatever we write,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1825
   *       so we will read in whatever we write out onto the bus.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1826
   *       We will therefore have to compare
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1827
   *       the first frame we read with the one we sent. If they are
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1828
   *       identical it is because we are in fact working on a RS-485
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1829
   *       bus and must therefore read in a second frame which will be
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1830
   *       the true response to our query.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1831
   *       If the first frame we receive is different to the query we
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1832
   *       just sent, then we are *not* working on a RS-485 bus, and
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1833
   *       that is already the real response to our query.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1834
   *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1835
   *       Flushing the input cache immediately after sending the query
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1836
   *       could solve this issue, but we have no guarantee that this
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1837
   *       process would not get swapped out between the write() and
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1838
   *       flush() calls, and we could therefore be flushing the response
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1839
   *       frame!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1840
   */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1841
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1842
  iter = 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1843
  while ((res = recv_length = read_frame(nd_entry, recv_data_ptr, ts_ptr, slave_id)) >= 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1844
    if (iter < INT_MAX) iter++;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1845
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1846
    if ((send_length <= 0) || (nd_entry->ignore_echo == 0))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1847
      /* any valid frame will do... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1848
      return recv_length;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1849
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1850
    if ((send_length > L2_FRAME_SLAVEID_OFS + 1) && (iter == 1))
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1851
     /* We have a frame in send_data,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1852
      * so we must make sure we are not reading in the frame just sent...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1853
      *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1854
      * We must only do this for the first frame we read. Subsequent
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1855
      * frames are guaranteed not to be the previously sent frame
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1856
      * since the modbus_rtu_write() resets the recv buffer.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1857
      * Remember too that valid modbus responses may be exactly the same
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1858
      * as the request frame!!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1859
      */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1860
      if (recv_length == send_length)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1861
        if (memcmp(*recv_data_ptr, send_data, recv_length) == 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1862
          /* recv == send !!! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1863
          /* read in another frame.  */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1864
          continue;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1865
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1866
    /* The frame read is either:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1867
     *  - different to the frame in send_data
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1868
     *  - or there is only the slave id in send_data[0]
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1869
     *  - or both of the above...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1870
     */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1871
    if (send_length > L2_FRAME_SLAVEID_OFS)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1872
      if (recv_length > L2_FRAME_SLAVEID_OFS)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1873
        /* check that frame is from/to the correct slave... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1874
        if ((*recv_data_ptr)[L2_FRAME_SLAVEID_OFS] == send_data[L2_FRAME_SLAVEID_OFS])
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1875
          /* yep, it is... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1876
          return recv_length;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1877
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1878
    /* The frame we have received is not acceptable...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1879
     * Let's read a new frame.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1880
     */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1881
  } /* while(...) */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1882
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1883
  /* error reading response! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1884
  /* Return the error returned by read_frame! */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1885
  return res;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1886
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1887
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1888
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1889
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1890
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1891
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1892
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1893
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1894
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1895
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1896
/****        Initialising and Shutting Down Library        ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1897
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1898
/****                                                      ****/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1899
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1900
/**************************************************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1901
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1902
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1903
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1904
/**   Load Default Values    **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1905
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1906
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1907
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1908
static void set_defaults(int *baud,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1909
                         int *parity,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1910
                         int *data_bits,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1911
                         int *stop_bits) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1912
  /* Set the default values, if required... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1913
  if (*baud == 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1914
    *baud = DEF_BAUD_RATE;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1915
  if (*data_bits == 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1916
    *data_bits = DEF_DATA_BITS;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1917
  if (*stop_bits == 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1918
    if (*parity == 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1919
      *stop_bits = DEF_STOP_BITS_NOP; /* no parity */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1920
    else
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1921
      *stop_bits = DEF_STOP_BITS_PAR; /* parity used */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1922
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1923
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1924
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1925
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1926
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1927
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1928
/**    Initialise Library    **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1929
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1930
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1931
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1932
int modbus_rtu_init(int nd_count,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1933
                    optimization_t opt,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1934
                    int *extra_bytes)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1935
{
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1936
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1937
  fprintf(stderr, "modbus_rtu_init(): called...\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1938
  fprintf(stderr, "creating %d node descriptors\n", nd_count);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1939
  if (opt == optimize_speed)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1940
    fprintf(stderr, "optimizing for speed\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1941
  if (opt == optimize_size)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1942
    fprintf(stderr, "optimizing for size\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1943
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1944
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1945
    /* check input parameters...*/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1946
  if (0 == nd_count) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1947
    if (extra_bytes != NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1948
      // Not the corect value for this layer. 
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1949
      // What we set it to in case this layer is not used!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1950
      *extra_bytes = 0; 
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1951
    return 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1952
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1953
  if (nd_count <= 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1954
    goto error_exit_0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1955
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1956
  if (extra_bytes == NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1957
    goto error_exit_0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1958
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1959
  if (crc_init(opt) < 0) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1960
#ifdef ERRMSG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1961
    fprintf(stderr, ERRMSG_HEAD "Out of memory: error initializing crc buffers\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1962
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1963
    goto error_exit_0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1964
  }
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1965
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1966
    /* set the extra_bytes value... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1967
    /* Please see note before the modbus_rtu_write() function for a
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1968
     * better understanding of this extremely ugly hack...
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1969
     *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1970
     * The number of extra bytes that must be allocated to the data buffer
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1971
     * before calling modbus_rtu_write()
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1972
     */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1973
  *extra_bytes = RTU_FRAME_CRC_LENGTH;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1974
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1975
    /* initialise nd table... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1976
  if (nd_table_init(&nd_table_, nd_count) < 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1977
    goto error_exit_0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1978
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1979
    /* remember the optimization choice for later reference... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1980
  optimization_ = opt;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1981
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1982
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1983
  fprintf(stderr, "modbus_rtu_init(): returning succesfuly...\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1984
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1985
  return 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1986
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1987
error_exit_0:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1988
  if (extra_bytes != NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1989
    // Not the corect value for this layer. 
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1990
    // What we set it to in case of error!
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1991
    *extra_bytes = 0; 
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1992
  return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1993
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1994
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1995
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1996
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1997
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1998
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  1999
/**    Open node descriptor  **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2000
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2001
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2002
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2003
/* Open a node for master or slave operation.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2004
 * Returns the node descriptor, or -1 on error.
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2005
 *
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2006
 * This function is mapped onto both
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2007
 * modbus_connect() and modbus_listen()
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2008
 */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2009
int modbus_rtu_connect(node_addr_t node_addr) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2010
  int node_descriptor;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2011
  nd_entry_t *nd_entry;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2012
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2013
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2014
  fprintf(stderr, "modbus_rtu_connect(): called...\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2015
  fprintf(stderr, "opening %s\n", node_addr.addr.rtu.device);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2016
  fprintf(stderr, "baud_rate = %d\n", node_addr.addr.rtu.baud);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2017
  fprintf(stderr, "parity = %d\n", node_addr.addr.rtu.parity);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2018
  fprintf(stderr, "data_bits = %d\n", node_addr.addr.rtu.data_bits);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2019
  fprintf(stderr, "stop_bits = %d\n", node_addr.addr.rtu.stop_bits);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2020
  fprintf(stderr, "ignore_echo = %d\n", node_addr.addr.rtu.ignore_echo);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2021
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2022
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2023
  /* Check for valid address family */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2024
  if (node_addr.naf != naf_rtu)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2025
    /* wrong address type... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2026
    goto error_exit_0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2027
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2028
  /* find a free node descriptor */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2029
  if ((node_descriptor = nd_table_get_free_nd(&nd_table_)) < 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2030
    /* if no free nodes to initialize, then we are finished... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2031
    goto error_exit_0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2032
  if ((nd_entry = nd_table_get_nd(&nd_table_, node_descriptor)) == NULL)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2033
    /* strange, this should not occur... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2034
    goto error_exit_0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2035
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2036
  /* set the default values... */
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2037
  set_defaults(&(node_addr.addr.rtu.baud),
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2038
               &(node_addr.addr.rtu.parity),
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2039
               &(node_addr.addr.rtu.data_bits),
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2040
               &(node_addr.addr.rtu.stop_bits));
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2041
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2042
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2043
  fprintf(stderr, "modbus_rtu_connect(): calling nd_entry_connect()\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2044
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2045
  if (nd_entry_connect(nd_entry, &node_addr, optimization_) < 0)
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2046
    goto error_exit_0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2047
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2048
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2049
  fprintf(stderr, "modbus_rtu_connect(): %s open\n", node_addr.addr.rtu.device);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2050
  fprintf(stderr, "modbus_rtu_connect(): returning nd=%d\n", node_descriptor);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2051
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2052
  return node_descriptor;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2053
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2054
  error_exit_0:
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2055
#ifdef DEBUG
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2056
  fprintf(stderr, "modbus_rtu_connect(): error!\n");
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2057
#endif
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2058
    return -1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2059
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2060
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2061
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2062
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2063
int modbus_rtu_listen(node_addr_t node_addr) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2064
  return modbus_rtu_connect(node_addr);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2065
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2066
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2067
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2068
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2069
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2070
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2071
/**   Close node descriptor  **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2072
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2073
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2074
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2075
int modbus_rtu_close(int nd) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2076
  return nd_table_free_nd(&nd_table_, nd);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2077
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2078
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2079
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2080
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2081
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2082
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2083
/**    Shutdown Library      **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2084
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2085
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2086
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2087
int modbus_rtu_done(void) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2088
  nd_table_done(&nd_table_);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2089
  crc_done();
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2090
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2091
  return 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2092
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2093
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2094
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2095
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2096
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2097
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2098
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2099
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2100
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2101
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2102
int modbus_rtu_silence_init(void) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2103
  return 0;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2104
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2105
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2106
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2107
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2108
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2109
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2110
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2111
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2112
/**                          **/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2113
/******************************/
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2114
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2115
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2116
double modbus_rtu_get_min_timeout(int baud,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2117
                                  int parity,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2118
                                  int data_bits,
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2119
                                  int stop_bits) {
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2120
  int parity_bits, start_bits, char_bits;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2121
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2122
  set_defaults(&baud, &parity, &data_bits, &stop_bits);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2123
  parity_bits = (parity == 0)?0:1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2124
  start_bits  = 1;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2125
  char_bits   = start_bits + data_bits + parity_bits + stop_bits;
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2126
  return (double)((MAX_RTU_FRAME_LENGTH * char_bits) / baud);
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2127
}
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2128
ae252e0fd9b8 Initial commit.
Mario de Sousa <msousa@fe.up.pt>
parents:
diff changeset
  2129