Beispiel #1
0
static int luaevent_loopexit(lua_State*L) {
	int ret;
	le_base *base = event_base_get(L, 1);
	struct timeval tv = { 0, 0 };
	if(lua_gettop(L) >= 2) /* Optional timeout before exiting the loop */
		load_timeval(luaL_checknumber(L, 2), &tv);
	ret = event_base_loopexit(base->base, &tv);
	lua_pushinteger(L, ret);
	return 1;
}
Beispiel #2
0
/* Index for coroutine is fd as integer for *nix, as lightuserdata for Win */
void luaevent_callback(int fd, short event, void* p) {
	le_callback* cb = p;
	lua_State* L;
	int ret;
	struct timeval new_tv = { 0, 0 };
	assert(cb);
	if(!cb->base)
		return; /* Event has already been collected + destroyed */
	assert(cb->base->loop_L);
	L = cb->base->loop_L;
	lua_rawgeti(L, LUA_REGISTRYINDEX, cb->callbackRef);
	lua_pushinteger(L, event);
	if(lua_pcall(L, 1, 2, 0))
	{
		cb->base->errorMessage = luaL_ref(L, LUA_REGISTRYINDEX);
		event_base_loopbreak(cb->base->base);
		lua_pop(L, 2);
		return;
	}
	if(!cb->base) {
		lua_pop(L, 2);
		return; /* event was destroyed during callback */
	}
	/* If nothing is returned, re-use the old event value */
	ret = luaL_optinteger(L, -2, event);
	/* Clone the old timeout value in case a new one wasn't set */
	memcpy(&new_tv, &cb->timeout, sizeof(new_tv));
	if(lua_isnumber(L, -1)) {
		double newTimeout = lua_tonumber(L, -1);
		if(newTimeout > 0) {
			load_timeval(newTimeout, &new_tv);
		}
	}
	lua_pop(L, 2);
	if(ret == -1) {
		freeCallbackArgs(cb, L);
	} else {
		struct event *ev = &cb->ev;
		int newEvent = ret;
		if( newEvent != event || (cb->timeout.tv_sec != new_tv.tv_sec || cb->timeout.tv_usec != new_tv.tv_usec) ) {
			struct timeval *ptv = &cb->timeout;
			cb->timeout = new_tv;
			if(!cb->timeout.tv_sec && !cb->timeout.tv_usec)
				ptv = NULL;
			event_del(ev);
			event_set(ev, fd, EV_PERSIST | newEvent, luaevent_callback, cb);
			/* Assume cannot set a new timeout.. */
			event_add(ev, ptv);
		}
	}
}
static unsigned int Receive()
{
  static int   			sts;
  unsigned char         	received_char = NUL;
  static unsigned char  	snak[2] = {NAK, NUL};
  static unsigned char  	sdle[2] = {DLE, NUL};
  //static int			error_logged = 0;

  fd_set read_fd;
  struct timeval tv;

/**** set up timeout ****/

  load_timeval(&tv, 0);		// poll
//  load_timeval(&tv, rn_3964R->ScanTime);
//  tv.tv_sec = TIMEOUT_REC_ANSWER_SEC;
//  tv.tv_usec = TIMEOUT_REC_ANSWER_USEC;

/**routine**/  

  FD_ZERO(&read_fd);
  FD_SET(ser_fd, &read_fd);
  sts=select(ser_fd+1, &read_fd, NULL, NULL, &tv);
  sts=read(ser_fd, &received_char, 1);

  if (sts > 0)
  {
    if (received_char == STX)
    {
      /* Write DLE to respond */
      if(!write(ser_fd, sdle, 1))
        return 0;
      sts = ReceiveHandler(ser_fd);
    }
    else
    {
      /* We don't understand, Send NAK unless NAK is received */
      if (received_char != NAK)
        write(ser_fd, snak, 1);
      errh_Error("3964R felaktigt meddelande i mottagning, annat starttecken än STX (0x%x)", received_char);
      sts=0;			//felstatus
    }

    if (sts < 1)
    {
      rn_3964R->ErrCount++;
    }
  }
  return(1);
}
Beispiel #4
0
/* Index for coroutine is fd as integer for *nix, as lightuserdata for Win */
void luaevent_callback(int fd, short event, void* p) {
	le_callback* cb = p;
	struct event *ev = &cb->ev;
	lua_State* L;
	int ret = -1;
	struct timeval new_tv = { 0, 0 };
	if(cb->callbackRef != LUA_NOREF) {
		L = cb->base->loop_L;
		lua_rawgeti(L, LUA_REGISTRYINDEX, cb->callbackRef);
		lua_pushinteger(L, event);
		cb->running = 1;
		if(lua_pcall(L, 1, 2, 0))
		{
			cb->running = 0;
			cb->base->errorMessage = luaL_ref(L, LUA_REGISTRYINDEX);
			event_base_loopbreak(cb->base->base);
			lua_pop(L, 1); /* Pop the 'false' from pcall */
			return;
		}
		cb->running = 0;
		/* If nothing is returned, re-use the old event value */
		ret = luaL_optinteger(L, -2, event);
	}
	if(ret == -1 || cb->callbackRef == LUA_NOREF) {
		event_del(ev);
		freeCallback(cb, L);
		assert(cb->selfRef != LUA_NOREF);
		luaL_unref(L, LUA_REGISTRYINDEX, cb->selfRef);
		cb->selfRef = LUA_NOREF;
	} else if( ret != event || (cb->timeout.tv_sec != new_tv.tv_sec || cb->timeout.tv_usec != new_tv.tv_usec) ) {
		/* Clone the old timeout value in case a new one wasn't set */
		memcpy(&new_tv, &cb->timeout, sizeof(new_tv));
		if(lua_isnumber(L, -1)) {
			double newTimeout = lua_tonumber(L, -1);
			if(newTimeout > 0) {
				load_timeval(newTimeout, &new_tv);
			}
		}
		struct timeval *ptv = &cb->timeout;
		cb->timeout = new_tv;
		if(!cb->timeout.tv_sec && !cb->timeout.tv_usec)
			ptv = NULL;
		event_del(ev);
		event_set(ev, fd, EV_PERSIST | ret, luaevent_callback, cb);
		/* Assume cannot set a new timeout.. */
			event_add(ev, ptv);
	}
	lua_pop(L, 2); /* Pop two results from call */
}
Beispiel #5
0
/* sock, event, callback, timeout */
static int luaevent_addevent(lua_State* L) {
	int fd, event;
	le_callback* arg = event_callback_push(L, 1, 4);
	struct timeval *tv = &arg->timeout;
	if(lua_isnil(L, 2) && lua_isnumber(L, 5)) {
		fd = -1; /* Per event_timer_set.... */
	} else {
		fd = getSocketFd(L, 2);
	}
	event = luaL_checkinteger(L, 3);
	if(lua_isnumber(L, 5)) {
		double time = lua_tonumber(L, 5);
		load_timeval(time, tv);
	} else {
		tv = NULL;
	}

	/* Setup event... */
	arg->ev = *event_new(arg->base->base, fd, event | EV_PERSIST, luaevent_callback, arg);
	event_add(&arg->ev, tv);
	return 1;
}
Beispiel #6
0
static unsigned int Receive()
{
  int sts;
  int nbr_of_bytes_read = 0;
  unsigned char telegram[512];
  char search_remtrans = FALSE;
  remtrans_item *remtrans;
 
  fd_set read_fd;
  struct timeval tv;

  load_timeval(&tv, rn_serial->ScanTime);
  
  nbr_of_bytes_read = 0;
  telegram[nbr_of_bytes_read] = 0;
  sts = 0;
  
  while (nbr_of_bytes_read < sizeof(telegram)-2)
  {
    // Om vi är under mottagning, vänta tills lästimeout
    if (nbr_of_bytes_read > 0) load_timeval(&tv, rn_serial->ReadTimeout);
    FD_ZERO(&read_fd);
    FD_SET(ser_fd, &read_fd);
    sts = select(ser_fd+1, &read_fd, NULL, NULL, &tv);
    if (sts > 0) { // Tecken finns att läsa
      sts = read(ser_fd, &telegram[nbr_of_bytes_read], 1);
      if(sts > 0) {
        nbr_of_bytes_read++;
        if (telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[0] ||
            telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[1] ||
            telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[2] ||
            telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[3] ||
            telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[4] ||
            telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[5] ||
            telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[6] ||
            telegram[nbr_of_bytes_read-1]==rn_serial->TermChar[7] )
          break;
      }
      else {  // Läsfel
        rn_serial->ErrCount++;        
        break;
      } 
    }
    else {  // Timeout
      break;
    }      
  }
   
  if (nbr_of_bytes_read > 0)  // Vi tog emot ett eller flera tecken
  {
    telegram[nbr_of_bytes_read] = 0;
    if (debug)
    {
      printf("Vi tog emot en trans med terminering 0x%x\n", telegram[nbr_of_bytes_read-1]);
      printf("Telegramet var:%s\n", telegram);
    }
    
    search_remtrans = true;
    remtrans = rn.remtrans;

    while (remtrans && search_remtrans)
    {
      if (remtrans->objp->Direction == REMTRANS_IN )
         search_remtrans = false;
      if ( search_remtrans ) remtrans = (remtrans_item *) remtrans->next;
    }   /* endwhile */

    if ( !search_remtrans )
    {
      sts = RemTrans_Receive(remtrans, (char *)telegram, nbr_of_bytes_read);
      if ( EVEN(sts) )
      {
        remtrans->objp->ErrCount++;
        return (FALSE);
      }
    }

    if (search_remtrans)
    {
      /* No corresponding RemTrans object found */
      rn_serial->ErrCount++;
      return (FALSE);
    }
  }

  return(1);
}
static unsigned int ReceiveHandler(int fd)
{
  unsigned int          sts;
  //unsigned int          nbr_of_bytes_written = 0;
  //unsigned int          nbr_of_bytes_read = 0;
  unsigned int          data_size = 0;
  unsigned int		io_size = 0;
  unsigned int		common_offset = 0;
  char                  cont = TRUE;
  char			search_remtrans = FALSE;
  char                  name[7];
  unsigned char         BCC = '\0';
  unsigned char         receive_buffer[MAX_SIZE_TELEGRAM];
  unsigned char         sdle = DLE;
  unsigned char		received_char;
  remtrans_item         *remtrans;
  int 			i;

  fd_set read_fd;
  struct timeval tv;
  char type_name[4];
  common_buffer_vnet *c_buf;

  /**** set up timeout,****/

  load_timeval(&tv, rn_3964R->CharTimeout);

//  tv.tv_sec = TIMEOUT_REC_CHAR_SEC;
//  tv.tv_usec = TIMEOUT_REC_CHAR_USEC;


/*************************************************************************/
/**    Read telegram	                                                **/
/*************************************************************************/

  cont = TRUE;
  data_size = 0;
  
  while (cont)
  {
    /* Read until DLE is received */

    received_char=0;

    while(received_char != DLE)
    {
      load_timeval(&tv, rn_3964R->CharTimeout);
      FD_ZERO(&read_fd);
      FD_SET(fd, &read_fd);
      select(fd+1, &read_fd, NULL, NULL, &tv);
      if (read(fd, &received_char, 1) > 0) { //om det inte var timeout
        // Prevent writing oob
        if (data_size > MAX_SIZE_TELEGRAM - 10) return (FALSE);
        receive_buffer[data_size++]=received_char;
      }
      else				//timeout gå tillbaka
      {
        errh_Error("3964R mottagning, character timeout");
        return(FALSE);  
      }
    }  

    /* Read one more */
    load_timeval(&tv, rn_3964R->CharTimeout);
    FD_ZERO(&read_fd);
    FD_SET(fd, &read_fd);
    select(fd+1, &read_fd, NULL, NULL, &tv);
    if (read(fd, &receive_buffer[data_size], 1) < 1) {
      errh_Error("3964R mottagning, character timeout");
      return(FALSE);  
    }
 
    if (receive_buffer[data_size] == ETX)
    {
      data_size++;

      /* Read one more, should be checksum */
      load_timeval(&tv, rn_3964R->CharTimeout);
      FD_ZERO(&read_fd);
      FD_SET(fd, &read_fd);
      select(fd+1, &read_fd, NULL, NULL, &tv);
      if (read(fd, &receive_buffer[data_size], 1) < 1) {
        errh_Error("3964R mottagning, character timeout");
        return(FALSE);  
      }
  
      data_size++;
      cont = FALSE;
    }
    else
      if (receive_buffer[data_size] != DLE ) data_size++;
  }

/*************************************************************************/
/**  A complete message is received. Check BCC.                         **/
/*************************************************************************/
  BCC = DLE ^ ETX;

  for (i=0; i<data_size-3; i++)
    if (receive_buffer[i] != DLE)
      BCC ^= receive_buffer[i];
  


  if ( BCC == receive_buffer[data_size-1] ) {
    if(!write(fd,&sdle, 1)) return(FALSE);
  }
  else
  {
    /* Checksum in this telegram is wrong */
    errh_Error("3964R mottagning, felaktig checksumma, %d, %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", 
    	data_size, receive_buffer[0], receive_buffer[1], receive_buffer[2], receive_buffer[3], receive_buffer[4], receive_buffer[5],
    	receive_buffer[6], receive_buffer[7], receive_buffer[8], receive_buffer[9], receive_buffer[10], receive_buffer[11]);
    if (debug) printf("  Checksum error\n");
       
    if (use_remote_io) {
      if(!write(fd,&sdle, 1)) return(FALSE);
    }
    else
      return(FALSE);
  }


/*************************************************************************/
/**  Find out if the received message is a array of io updates.         **/
/**  Treat the message and exit.                                        **/
/*************************************************************************/
  {
    io_buffer_vnet *io_buf = (io_buffer_vnet *) &receive_buffer;
    RemUtils_R50ToAscii((unsigned short *) &io_buf->io_name, (char *) &name);

    if (strstr(name, "PSS")) {
      io_size = io_buf->length * 2;     /* Converted to bytes */
      sts = RemIO_Receive_3964R(&rn,
                                (unsigned char *) &io_buf->data,
                                io_size-NET_HEADER_SIZE_IO);
      if (debug) printf("  Receiving I/O area\n");

      time_since_io = 0;
      rn_3964R->LinkUp = 1;

      return(sts);
    }
  }

/*************************************************************************/
/**  Find out if the received message is a array of common data         **/
/**  Search for the RemTrans object that is the target.                 **/
/*************************************************************************/
  c_buf = (common_buffer_vnet *) &receive_buffer;

  RemUtils_R50ToAscii((unsigned short *) &c_buf->common_name, (char *) &name);
  for ( i=0 ; i<4 ; i++ )
  {
    type_name[i] = name[i+3];
  }
  if ( (strncmp(type_name, "COM", 3)) == 0 ){
    search_remtrans = true;
    remtrans = rn.remtrans;
    while(remtrans && search_remtrans)
    {
      if ( remtrans->objp->Address[0] == c_buf->common_name[0] &&
             remtrans->objp->Address[1] == c_buf->common_name[1]    )
          search_remtrans = false;
      if ( search_remtrans )
          remtrans = (remtrans_item *) remtrans->next;
    }   /* endwhile */

/*************************************************************************/
/**  Treat the common data update message and exit.                     **/
/*************************************************************************/
    if ( !search_remtrans ){
      io_size = c_buf->length * 2;     /* Converted to bytes */
      common_offset = c_buf->offset;

      if (io_size > remtrans->objp->MaxLength ){
        remtrans->objp->ErrCount++;
        remtrans->objp->LastSts = STATUS_LENGTH;
        return(FALSE);
      }
      else { 
        memcpy(&remtrans->datap[common_offset], c_buf, io_size);
	time_GetTime(&remtrans->objp->TransTime);
        remtrans->objp->TransCount++;
        remtrans->objp->DataValid = TRUE;
        remtrans->objp->LastSts = STATUS_OK;
        remtrans->objp->DataLength = data_size;
      }
      return(TRUE);
    }
  }
  
/*************************************************************************/
/**   This message contains a ordinary remtrans                         **/
/**   Search for the RemTrans object that is the target.                **/
/**   If remote I/O is not used, the message is stored in the first     **/
/**   found (ingoing) remtrans object. If we use remote I/O we check for**/
/**   matching message header                                           **/
/*************************************************************************/
  search_remtrans = true;
  remtrans = rn.remtrans;
  while(remtrans && search_remtrans)
  {
    if (remtrans->objp->Direction == REMTRANS_IN) {
      if (!use_remote_io) {
        search_remtrans = false;
      }
      else {
        if (remtrans->objp->Address[0] == c_buf->common_name[0] &&
	    remtrans->objp->Address[1] == c_buf->common_name[1])
              search_remtrans = false;
      }
    }
    if ( search_remtrans ) remtrans = (remtrans_item *) remtrans->next;
  }
 
/*************************************************************************/
/**  Treat the remtrans message and exit.                               **/
/*************************************************************************/
  if (!search_remtrans)
  {
    sts = RemTrans_Receive(remtrans, (char *)receive_buffer, data_size-3);
    if ( EVEN(sts) )
    {
      remtrans->objp->ErrCount++;
      return (FALSE);
    }
  }
  else
  {
    /* No remtrans */
    errh_Error("Remtrans 3964R no remtrans for this message");
    rn_3964R->ErrCount++;
    return (FALSE);
  }
  return (TRUE);
}
static unsigned int send_it(char *buf, int buffer_size)
{
  int          		sts, i;
  unsigned int          size_of_telegram;
  unsigned int          number_of_DLE = 0;
  unsigned char         ch;
  unsigned char         BCC = DLE ^ ETX;
  unsigned char         *restore_buf_ptr = (unsigned char *)buf;
  unsigned char         telegram[MAX_SIZE_TELEGRAM];
  unsigned char		buff;
  static unsigned char  sstx[2] = {STX, '\0'};
  //static unsigned char  sdle[2] = {DLE, '\0'};
  static unsigned char  snak[2] = {NAK, '\0'};

  fd_set read_fd;
  struct timeval tv;

/*************************************************************************/
/** Count DLE characters and calculate the size of the telegram.        **/
/*************************************************************************/
  for ( i=0 ; i < buffer_size ; i++ )
  {
    if ( *buf++ == DLE )
      number_of_DLE += 1;
  }
  size_of_telegram = buffer_size + number_of_DLE + NUMBER_OF_STOP_CHAR;
  
/*************************************************************************/
/**   Fill up telegram with contents of message and calculate BCC       **/
/*************************************************************************/
  buf = (char *)restore_buf_ptr;
  for ( i=0 ; i<(buffer_size + number_of_DLE) ; i++ )
  {
    ch = telegram[i] = *buf++;
    BCC ^= ch;
    if ( ch == DLE )
    {
      telegram[++i] = DLE;
      BCC ^= ch;
    }
  }
  telegram[i++] = DLE;
  telegram[i++] = ETX;
  telegram[i]   = BCC;

/*************************************************************************/
/**    Execute the send procedure      **/
/*************************************************************************/

/**** set up timeout ****/

//  tv.tv_sec = TIMEOUT_SND_ANSWER_SEC;
//  tv.tv_usec = TIMEOUT_SND_ANSWER_USEC;
  load_timeval(&tv, rn_3964R->AckTimeout);

  FD_ZERO(&read_fd);
  FD_SET(ser_fd, &read_fd);

  sts=TRUE;
  
  write(ser_fd, sstx, 1); 	/*send stx and wait for answer*/
    
  select(ser_fd+1, &read_fd, NULL, NULL, &tv);	/*wait for char or timeout*/
  sts=read(ser_fd,&buff,1);			/*read port*/
  
  if(sts < 1)				/*if timeout*/
  {
    errh_Error("Remtrans 3964R, sändning, inget svar från mottagaren, försöker igen");
    write(ser_fd, sstx, 1);	/*try once more*/

    FD_ZERO(&read_fd);
    FD_SET(ser_fd, &read_fd);
    load_timeval(&tv, rn_3964R->AckTimeout);
    select(ser_fd+1, &read_fd, NULL, NULL, &tv);
    sts=read(ser_fd,&buff,1);
  }
  
  if(sts > 0 && buff==DLE)			/*if DLE ok send telegram*/
  {
    write(ser_fd, telegram, size_of_telegram);

//    tv.tv_sec = TIMEOUT_SND_ANSWER_SEC;
//    tv.tv_usec = TIMEOUT_SND_ANSWER_USEC;
    load_timeval(&tv, rn_3964R->AckTimeout);
    FD_ZERO(&read_fd);
    FD_SET(ser_fd, &read_fd);
    select(ser_fd+1, &read_fd, NULL, NULL, &tv);
    sts=read(ser_fd,&buff,1); 
  }
  
  if(sts < 1 || buff!=DLE)			/*if somthing went wrong*/
  {
    write(ser_fd,snak, 1);
    if(sts<1)
      errh_Error("Remtrans 3964R sändning misslyckades, inget initierande DLE-tecken från mottagaren");
    else if(buff!=DLE)
      errh_Error("Remtrans 3964R sändning misslyckades, inget avslutande DLE-tecken från mottagaren");
    sts=FALSE;
  }
  return sts;				/*and return status*/
}
static unsigned int remnode_send(remnode_item *remnode,
                                 pwr_sClass_RemTrans *remtrans,
                                 char *buf,
                                 int buf_size)
{
  unsigned int          sts, i;
  unsigned int          size_of_telegram, datasize;
  unsigned int          number_of_DLE = 0;
  unsigned int          delta_pos = 0;
  unsigned int          pos_counter = 0;
  unsigned int          follow_on = FALSE;
  unsigned int          A_telegram = FALSE;
  unsigned char         ch, cpu_number, CPU;
  unsigned char         BCC = DLE ^ ETX;
  unsigned char         datasize_low_byte, datasize_high_byte;
  unsigned char         received_char = '\0';
  unsigned char         response_buffer[RESP_MESSAGE_SIZE];
  unsigned char         *restore_buf_ptr = (unsigned char *)buf;
  static unsigned char  sstx[2] = {STX, '\0'};
  static unsigned char  sdle[2] = {DLE, '\0'};
  static unsigned char  snak[2] = {NAK, '\0'};
  fd_set read_fd;
  struct timeval tv;


  /* Define complete telegrams for sending */

  struct{
    unsigned char telegram_header[HEADER_SIZE];
    unsigned char telegram[MAX_SIZE_DATA_BLOCK*2 + NUMBER_OF_STOP_CHAR];
  }sendbuffer;

  struct{
    unsigned char telegram_header[FOLLOW_ON_HEADER_SIZE];
    unsigned char telegram[MAX_SIZE_DATA_BLOCK*2 + NUMBER_OF_STOP_CHAR];
  }follow_on_sendbuffer;


  do     /* Send 128 byte telegrams until message is finished */
  {
    if ( !follow_on )
    {
      A_telegram = TRUE;
/*************************************************************************/
/**    Send A-telegram.                                                 **/
/*************************************************************************/
/**    Check if follow on telegrams are needed.                         **/
/*************************************************************************/
      if ( buf_size - pos_counter > MAX_SIZE_DATA_BLOCK )
      {
        delta_pos = MAX_SIZE_DATA_BLOCK;
        follow_on = TRUE;
      }
      else
      {
        delta_pos = buf_size - pos_counter;
      }

/*************************************************************************/
/**    Calculate the size of the A-telegram.                            **/
/*************************************************************************/
      /* Count DLE characters */
      for ( i=0 ; i<delta_pos ; i++ )
      {
         if ( *buf++ == DLE )
            number_of_DLE += 1;
      }
      size_of_telegram = HEADER_SIZE+
                         delta_pos+number_of_DLE+NUMBER_OF_STOP_CHAR;

/*************************************************************************/
/**    Fill in the telegram header and calculate BCC.                   **/
/*************************************************************************/
      /* Size have to be expressed in number of 16 bits words. */
      /* If odd number of bytes add one. */

      datasize = buf_size/2 + buf_size%2;
      datasize_low_byte = (unsigned char)(BYTE_MASK & datasize);
      datasize = datasize >> 8;
      datasize_high_byte = (unsigned char)(BYTE_MASK & datasize);
      cpu_number = (unsigned char)remtrans->Address[2];
      CPU = '\xFF';
      CPU = CPU_NR_MASK & cpu_number;

      sendbuffer.telegram_header[0] = '\0';
      sendbuffer.telegram_header[1] = '\0';
      sendbuffer.telegram_header[2] = 'A';
      sendbuffer.telegram_header[3] = 'D';
      sendbuffer.telegram_header[4] = (unsigned char)remtrans->Address[0];
      sendbuffer.telegram_header[5] = (unsigned char)remtrans->Address[1];
      sendbuffer.telegram_header[6] = datasize_high_byte;
      sendbuffer.telegram_header[7] = datasize_low_byte;
      sendbuffer.telegram_header[8] = '\xFF';
      sendbuffer.telegram_header[9] = CPU;

      /* Calculate checksum for the header */
      for ( i=0 ; i<HEADER_SIZE ; i++ )
      {
        BCC ^= sendbuffer.telegram_header[i];
      }
/*************************************************************************/
/**   Fill up A-telegram with contents of message and calculate BCC     **/
/*************************************************************************/
      buf = (char *)restore_buf_ptr;
      for ( i=0 ; i<(delta_pos+number_of_DLE) ; i++ )
      {
        ch = sendbuffer.telegram[i] = *buf++;
        BCC ^= ch;
        if ( ch == DLE )
        {
          sendbuffer.telegram[++i] = DLE;
          BCC ^= ch;
        }
      }
      if ( delta_pos%2 )
      {
        /* Ensure that a even number of bytes is treated */
        sendbuffer.telegram[i++] = '\0';
        size_of_telegram += 1;
      }
      sendbuffer.telegram[i++] = DLE;
      sendbuffer.telegram[i++] = ETX;
      sendbuffer.telegram[i]   = BCC;

      pos_counter = delta_pos;
    }
    else  /* follow on telegram */
    {

/*************************************************************************/
/**    Send follow on telegram.                                         **/
/*************************************************************************/
/**    Check if more follow on telegrams are needed.                    **/
/*************************************************************************/
      if ( buf_size - pos_counter > MAX_SIZE_DATA_BLOCK )
      {
        delta_pos = MAX_SIZE_DATA_BLOCK;
        follow_on = TRUE;
      }
      else
      {
        delta_pos = buf_size - pos_counter;
        follow_on = FALSE;
      }

/*************************************************************************/
/**    Calculate the size of the follow on telegram.                    **/
/*************************************************************************/
      /* Count DLE characters */
      restore_buf_ptr = (unsigned char *)buf;
      number_of_DLE = 0;
      for ( i=0 ; i<delta_pos ; i++ )
      {
         if ( *buf++ == DLE )
            number_of_DLE += 1;
      }
      size_of_telegram = FOLLOW_ON_HEADER_SIZE+
                         delta_pos+number_of_DLE+NUMBER_OF_STOP_CHAR;

/*************************************************************************/
/**    Fill in the follow on telegram header and calculate BCC.         **/
/*************************************************************************/
      follow_on_sendbuffer.telegram_header[0] = '\xFF';
      follow_on_sendbuffer.telegram_header[1] = '\0';
      follow_on_sendbuffer.telegram_header[2] = 'A';
      follow_on_sendbuffer.telegram_header[3] = 'D';

      /* Calculate checksum for the header */
      BCC = DLE ^ ETX;
      for ( i=0 ; i<FOLLOW_ON_HEADER_SIZE ; i++ )
      {
        BCC ^= follow_on_sendbuffer.telegram_header[i];
      }

/*************************************************************************/
/* Fill up follow on telegram with contents of message and calculate BCC */
/*************************************************************************/
      buf = (char *)restore_buf_ptr;
      for ( i = 0 ; i < (delta_pos+number_of_DLE) ; i++ )
      {
        ch = follow_on_sendbuffer.telegram[i] = *buf++;
        BCC ^= ch;
        if ( ch == DLE )
        {
          follow_on_sendbuffer.telegram[++i] = DLE;
          BCC ^= ch;
        }
      }
      if ( delta_pos%2 )
      {
        /* Ensure that a even number of bytes is treated */
        follow_on_sendbuffer.telegram[i++] = '\0';
        size_of_telegram += 1;
      }
      follow_on_sendbuffer.telegram[i++] = DLE;
      follow_on_sendbuffer.telegram[i++] = ETX;
      follow_on_sendbuffer.telegram[i]   = BCC;

      pos_counter += delta_pos;

    }

/*************************************************************************/
/**    Execute the send procedure                                       **/
/*************************************************************************/
    /* Send STX and wait for answer */
    sts = write(ser_fd, sstx, 1);
    rlog("snd STX", 0);
    if ( sts > 0) {
      load_timeval(&tv, rn_RK512->CharTimeout);
      FD_ZERO(&read_fd);
      FD_SET(ser_fd, &read_fd);
      select(ser_fd+1, &read_fd, NULL, NULL, &tv);
      sts = read(ser_fd, &received_char, 1);
    }
    if ( sts > 0) { //om det inte var timeout

      if ( received_char == STX ) {
	rlog("snd STX received", 0);
	/* Both nodes is in sending mode. */
	/* Cancel this send operation and wait for next timeout or receive */
	write(ser_fd, snak, 1);
	return(FALSE);
      }
      if ( received_char == DLE ) {
	/* Contact is established. Send telegram */
	rlog("snd DLE received, contact", 0);
	if ( A_telegram ) {
	  sts = write(ser_fd, &sendbuffer, size_of_telegram);
	  rlog("snd message sent", size_of_telegram);
	  A_telegram = FALSE;
	}
	else {
	  sts = write(ser_fd, &follow_on_sendbuffer, size_of_telegram);
	  rlog("snd message sent", size_of_telegram);
	}
	if ( sts > 0 ) {
	  /* wait for break character or timeout */
	  load_timeval(&tv, rn_RK512->CharTimeout);
	  FD_ZERO(&read_fd);
	  FD_SET(ser_fd, &read_fd);
	  select(ser_fd+1, &read_fd, NULL, NULL, &tv);
	  sts = read(ser_fd, &received_char, 1);

          if ( sts > 0 &&(received_char == DLE) ) {

/*************************************************************************/
/**   The sending was a SUCCESS. Take care of the response message      **/
/*************************************************************************/
	    rlog("snd DLE received, success", 0);
	    load_timeval(&tv, rn_RK512->CharTimeout);
	    FD_ZERO(&read_fd);
	    FD_SET(ser_fd, &read_fd);
	    select(ser_fd+1, &read_fd, NULL, NULL, &tv);
	    sts = read(ser_fd, &received_char, 1);

            if ( sts > 0 &&(received_char == STX) ) {
              /* Send DLE acknowledge and wait for response data */
	      sts = write(ser_fd, sdle, 1);
              if ( sts > 0 ) {
                BCC = '\0';
                for (i=0 ;
                     i < RESP_MESSAGE_SIZE && sts > 0;
                     i++ ) {

		  load_timeval(&tv, rn_RK512->CharTimeout);
		  FD_ZERO(&read_fd);
		  FD_SET(ser_fd, &read_fd);
		  select(ser_fd+1, &read_fd, NULL, NULL, &tv);
		  sts = read(ser_fd, &received_char, 1);

                  response_buffer[i] = received_char;
                  BCC ^= received_char;
                }  /* endfor */

                if ( sts > 0 &&
                     (response_buffer[2] == '\0') ) {
                  /* Compare received BCC with calculated */
		  load_timeval(&tv, rn_RK512->CharTimeout);
		  FD_ZERO(&read_fd);
		  FD_SET(ser_fd, &read_fd);
		  select(ser_fd+1, &read_fd, NULL, NULL, &tv);
		  sts = read(ser_fd, &received_char, 1);
                  if ( sts > 0 &&
                       ( BCC == received_char ) ) {
                    /* Response telegram received OK */
		    sts = write(ser_fd, sdle, 1);
                    if ( response_buffer[3] != 0 ) {
                      /* This response contains a error code */
                      errh_CErrLog(REM__SIEMENSERROR,
                                   errh_ErrArgL(response_buffer[3]) );
                    }
                  }
                  else {
                    /* Wrong checksum. */
                    sts = FALSE;
                  }
                }
                else {
                  /* This is not a response message as expected */
		  sts = write(ser_fd, snak, 1);
                  sts = FALSE;
                }
              } /* ENDIF. DLE acknowledge failed */
            }
            else
            {
              /* STX character in response message was expected. */
              /* Ensure that error status is returned */
              sts = FALSE;
            }
          }
          else
          {
            /* DLE ack. after sending telegram was expected. */
            /* Ensure that error status is returned */
	    rlog("snd DLE missing", 0);
            sts = FALSE;
          }
        } /* ENDIF. Contact established but tty_write failed */
      }
      else
      {
        /* Failed in making contact. Wrong response character. */
        /* Ensure that error status is returned */
        sts = FALSE;
      }
    }  /* ENDIF. tty_write or tty_read failed */

/*************************************************************************/
/**  Check final status.                                                **/
/*************************************************************************/
    if ( EVEN(sts))
    {
      /* The send procedure has failed */
      sts = write(ser_fd, snak, 1);
      rlog("snd failed, NAK sent", 0);

      follow_on = FALSE;

      /* Ensure that error status is returned */
      sts = FALSE;
    }

  }while( follow_on );