int read_packet(int id) { int ret = read_header(id); /* * Since we are reading with no timeout, * a positive value indicates that the header is complete. */ if(ret > 0) { ret = read_value(id); /* * Since we are reading with no timeout, * a non-negative value indicates that the value is complete. */ if(ret >= 0) { ret = adapter_process_packet(id, serials[id].data); serials[id].bread = 0; } } return ret; }
/* * \brief This function tries to read 'size' bytes of data. * * It blocks until 'size' bytes of data have been read or after 1s has elapsed. * It should only be used in the initialization stages, i.e. before the mainloop. * * \param id the instance id * \param pdata the pointer where to store the data * \param size the number of bytes to retrieve * * \return the number of bytes actually read */ int serial_recv(int id, void* pdata, unsigned int size) { int bread = 0; int res; fd_set readfds; struct timeval timeout = {.tv_sec = 1, .tv_usec = 0}; while(bread != size) { FD_ZERO(&readfds); FD_SET(serials[id].fd, &readfds); int status = select(serials[id].fd+1, &readfds, NULL, NULL, &timeout); if(status > 0) { if(FD_ISSET(serials[id].fd, &readfds)) { res = read(serials[id].fd, pdata, size-bread); if(res > 0) { bread += res; } } } else if(status == EINTR) { continue; } else { break; } } return bread; } /* * \brief This function closes a serial port. * * \param id the instance id * * \return 0 */ int serial_close(int id) { if(serials[id].fd >= 0) { usleep(10000);//sleep 10ms to leave enough time for the last packet to be sent close(serials[id].fd); serials[id].fd = -1; } return 0; } /* * \brief the serial callback for serial ports that are added as event sources. * * \param id the instance id * * \return 0 in case of a success, -1 in case of an error */ static int serial_callback(int id) { int nread; int ret = 0; unsigned char* base = (unsigned char*)&serials[id].packet; if(serials[id].bread < HEADER_SIZE) { /* * read the first two bytes first so as to retrieve the data length */ nread = read(serials[id].fd, base+serials[id].bread, HEADER_SIZE-serials[id].bread); if(nread >= 0) { serials[id].bread += nread; } else { fprintf(stderr, "%s:%d read: %m", __FILE__, __LINE__); ret = -1; } } else { /* * read the data */ nread = read(serials[id].fd, base+serials[id].bread, serials[id].packet.header.length-(serials[id].bread-HEADER_SIZE)); if(nread >= 0) { serials[id].bread += nread; if(serials[id].packet.header.length + HEADER_SIZE == serials[id].bread) { ret = adapter_process_packet(id, &serials[id].packet); serials[id].bread = 0; } } else { fprintf(stderr, "%s:%d read: %m", __FILE__, __LINE__); ret = -1; } } return ret; }