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; }
/* 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); }
/* 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 */ }
/* 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; }
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 );