00001
00010 #include "urg_c/urg_ring_buffer.h"
00011 #include <fcntl.h>
00012 #include <unistd.h>
00013
00014
00015 enum {
00016 INVALID_FD = -1,
00017 };
00018
00019
00020 static void serial_initialize(urg_serial_t *serial)
00021 {
00022 serial->fd = INVALID_FD;
00023 serial->has_last_ch = False;
00024
00025 ring_initialize(&serial->ring, serial->buffer, RING_BUFFER_SIZE_SHIFT);
00026 }
00027
00028
00029 static void serial_clear(urg_serial_t* serial)
00030 {
00031 tcdrain(serial->fd);
00032 tcflush(serial->fd, TCIOFLUSH);
00033 ring_clear(&serial->ring);
00034 serial->has_last_ch = False;
00035 }
00036
00037
00038 int serial_open(urg_serial_t *serial, const char *device, long baudrate)
00039 {
00040 int flags = 0;
00041 int ret = 0;
00042
00043 serial_initialize(serial);
00044
00045 #ifndef URG_MAC_OS
00046 enum { O_EXLOCK = 0x0 };
00047 #endif
00048 serial->fd = open(device, O_RDWR | O_EXLOCK | O_NONBLOCK | O_NOCTTY);
00049 if (serial->fd < 0) {
00050
00051
00052 return -1;
00053 }
00054
00055 flags = fcntl(serial->fd, F_GETFL, 0);
00056 fcntl(serial->fd, F_SETFL, flags & ~O_NONBLOCK);
00057
00058
00059 tcgetattr(serial->fd, &serial->sio);
00060 serial->sio.c_iflag = 0;
00061 serial->sio.c_oflag = 0;
00062 serial->sio.c_cflag &= ~(CSIZE | PARENB | CSTOPB);
00063 serial->sio.c_cflag |= CS8 | CREAD | CLOCAL;
00064 serial->sio.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN);
00065
00066 serial->sio.c_cc[VMIN] = 0;
00067 serial->sio.c_cc[VTIME] = 0;
00068
00069
00070 ret = serial_set_baudrate(serial, baudrate);
00071 if (ret < 0) {
00072 return ret;
00073 }
00074
00075
00076 serial->has_last_ch = False;
00077
00078 return 0;
00079 }
00080
00081
00082 void serial_close(urg_serial_t *serial)
00083 {
00084 if (serial->fd >= 0) {
00085 close(serial->fd);
00086 serial->fd = INVALID_FD;
00087 }
00088 }
00089
00090
00091 int serial_set_baudrate(urg_serial_t *serial, long baudrate)
00092 {
00093 long baudrate_value = -1;
00094
00095 switch (baudrate) {
00096 case 4800:
00097 baudrate_value = B4800;
00098 break;
00099
00100 case 9600:
00101 baudrate_value = B9600;
00102 break;
00103
00104 case 19200:
00105 baudrate_value = B19200;
00106 break;
00107
00108 case 38400:
00109 baudrate_value = B38400;
00110 break;
00111
00112 case 57600:
00113 baudrate_value = B57600;
00114 break;
00115
00116 case 115200:
00117 baudrate_value = B115200;
00118 break;
00119
00120 default:
00121 return -1;
00122 }
00123
00124
00125 cfsetospeed(&serial->sio, baudrate_value);
00126 cfsetispeed(&serial->sio, baudrate_value);
00127 tcsetattr(serial->fd, TCSADRAIN, &serial->sio);
00128 serial_clear(serial);
00129
00130 return 0;
00131 }
00132
00133
00134 int serial_write(urg_serial_t *serial, const char *data, int size)
00135 {
00136 if (serial->fd == INVALID_FD) {
00137 return -1;
00138 }
00139 return write(serial->fd, data, size);
00140 }
00141
00142
00143 static int wait_receive(urg_serial_t* serial, int timeout)
00144 {
00145 fd_set rfds;
00146 struct timeval tv;
00147
00148
00149 FD_ZERO(&rfds);
00150 FD_SET(serial->fd, &rfds);
00151
00152 tv.tv_sec = timeout / 1000;
00153 tv.tv_usec = (timeout % 1000) * 1000;
00154
00155 if (select(serial->fd + 1, &rfds, NULL, NULL,
00156 (timeout < 0) ? NULL : &tv) <= 0) {
00157
00158 return 0;
00159 }
00160 return 1;
00161 }
00162
00163
00164 static int internal_receive(char data[], int data_size_max,
00165 urg_serial_t* serial, int timeout)
00166 {
00167 int filled = 0;
00168
00169 if (data_size_max <= 0) {
00170 return 0;
00171 }
00172
00173 while (filled < data_size_max) {
00174 int require_n;
00175 int read_n;
00176
00177 if (! wait_receive(serial, timeout)) {
00178 break;
00179 }
00180
00181 require_n = data_size_max - filled;
00182 read_n = read(serial->fd, &data[filled], require_n);
00183 if (read_n <= 0) {
00184
00185 break;
00186 }
00187 filled += read_n;
00188 }
00189 return filled;
00190 }
00191
00192
00193 int serial_read(urg_serial_t *serial, char *data, int max_size, int timeout)
00194 {
00195 int buffer_size;
00196 int read_n;
00197 int filled = 0;
00198
00199 if (max_size <= 0) {
00200 return 0;
00201 }
00202
00203
00204 if (serial->has_last_ch != False) {
00205 data[0] = serial->last_ch;
00206 serial->has_last_ch = False;
00207 ++filled;
00208 }
00209 if (serial->fd == INVALID_FD) {
00210 if (filled > 0) {
00211 return filled;
00212 } else {
00213 return -1;
00214 }
00215 }
00216
00217 buffer_size = ring_size(&serial->ring);
00218 read_n = max_size - filled;
00219 if (buffer_size < read_n) {
00220
00221 char buffer[RING_BUFFER_SIZE];
00222 int n = internal_receive(buffer,
00223 ring_capacity(&serial->ring) - buffer_size,
00224 serial, 0);
00225 if (n > 0) {
00226 ring_write(&serial->ring, buffer, n);
00227 buffer_size += n;
00228 }
00229 }
00230
00231
00232 if (read_n > buffer_size) {
00233 read_n = buffer_size;
00234 }
00235 if (read_n > 0) {
00236 ring_read(&serial->ring, &data[filled], read_n);
00237 filled += read_n;
00238 }
00239
00240
00241 filled += internal_receive(&data[filled], max_size - filled,
00242 serial, timeout);
00243 return filled;
00244 }