]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/hokuyo/lib/serial_ctrl_lin.c
Fix a compile error on recent systems
[eurobot/public.git] / src / hokuyo / lib / serial_ctrl_lin.c
1 /*!
2   \file
3   \brief \83V\83\8a\83A\83\8b\92Ê\90M (Linux, Mac \8eÀ\91\95)
4
5   Serial Communication Interface \90§\8cä
6
7
8   \author Satofumi KAMIMURA
9
10   $Id: serial_ctrl_lin.c 1559 2009-12-01 13:13:08Z satofumi $
11 */
12
13 #include "serial_errno.h"
14 #include "ring_buffer.h"
15 #include <unistd.h>
16 #include <stdio.h>
17 #include <fcntl.h>
18 #include <errno.h>
19 #include <string.h>
20
21 //#include <ctype.h>
22
23 enum {
24   False = 0,
25   True,
26 };
27
28
29 enum {
30   InvalidFd = -1,
31 };
32
33
34 void serial_initialize(serial_t *serial)
35 {
36   serial->fd_ = InvalidFd;
37   serial->errno_ = SerialNoError;
38   serial->has_last_ch_ = False;
39
40   ring_initialize(&serial->ring_, serial->buffer_, RingBufferSizeShift);
41 }
42
43
44 /* \90Ú\91± */
45 int serial_connect(serial_t *serial, const char *device, long baudrate)
46 {
47   int flags = 0;
48   int ret = 0;
49
50   serial_initialize(serial);
51
52 #ifndef MAC_OS
53   enum { O_EXLOCK = 0x0 }; /* Linux \82Å\82Í\8eg\82¦\82È\82¢\82Ì\82Å\83_\83~\81[\82ð\8dì\90¬\82µ\82Ä\82¨\82­ */
54 #endif
55   serial->fd_ = open(device, O_RDWR | O_EXLOCK | O_NONBLOCK | O_NOCTTY);
56   if (serial->fd_ < 0) {
57     /* \90Ú\91±\82É\8e¸\94s */
58     strerror_r(errno, serial->error_string_, SerialErrorStringSize);
59     return SerialConnectionFail;
60   }
61
62   flags = fcntl(serial->fd_, F_GETFL, 0);
63   fcntl(serial->fd_, F_SETFL, flags & ~O_NONBLOCK);
64
65   /* \83V\83\8a\83A\83\8b\92Ê\90M\82Ì\8f\89\8aú\89» */
66   tcgetattr(serial->fd_, &serial->sio_);
67   serial->sio_.c_iflag = 0;
68   serial->sio_.c_oflag = 0;
69   serial->sio_.c_cflag &= ~(CSIZE | PARENB | CSTOPB);
70   serial->sio_.c_cflag |= CS8 | CREAD | CLOCAL;
71   serial->sio_.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN);
72
73   serial->sio_.c_cc[VMIN] = 0;
74   serial->sio_.c_cc[VTIME] = 0;
75
76   /* \83{\81[\83\8c\81[\83g\82Ì\95Ï\8dX */
77   ret = serial_setBaudrate(serial, baudrate);
78   if (ret < 0) {
79     return ret;
80   }
81
82   /* \83V\83\8a\83A\83\8b\90§\8cä\8d\\91¢\91Ì\82Ì\8f\89\8aú\89» */
83   serial->has_last_ch_ = False;
84
85   return 0;
86 }
87
88
89 /* \90Ø\92f */
90 void serial_disconnect(serial_t *serial)
91 {
92   if (serial->fd_ >= 0) {
93     close(serial->fd_);
94     serial->fd_ = InvalidFd;
95   }
96 }
97
98
99 int serial_isConnected(const serial_t *serial)
100 {
101   return ((serial == NULL) || (serial->fd_ == InvalidFd)) ? 0 : 1;
102 }
103
104
105 /* \83{\81[\83\8c\81[\83g\82Ì\90Ý\92è */
106 int serial_setBaudrate(serial_t *serial, long baudrate)
107 {
108   long baudrate_value = -1;
109
110   switch (baudrate) {
111   case 4800:
112     baudrate_value = B4800;
113     break;
114
115   case 9600:
116     baudrate_value = B9600;
117     break;
118
119   case 19200:
120     baudrate_value = B19200;
121     break;
122
123   case 38400:
124     baudrate_value = B38400;
125     break;
126
127   case 57600:
128     baudrate_value = B57600;
129     break;
130
131   case 115200:
132     baudrate_value = B115200;
133     break;
134
135   default:
136     return SerialSetBaudrateFail;
137   }
138
139   /* \83{\81[\83\8c\81[\83g\95Ï\8dX */
140   cfsetospeed(&serial->sio_, baudrate_value);
141   cfsetispeed(&serial->sio_, baudrate_value);
142   tcsetattr(serial->fd_, TCSADRAIN, &serial->sio_);
143   serial_clear(serial);
144
145   return 0;
146 }
147
148
149 /* \91\97\90M */
150 int serial_send(serial_t *serial, const char *data, int data_size)
151 {
152   if (! serial_isConnected(serial)) {
153     return SerialConnectionFail;
154   }
155   return write(serial->fd_, data, data_size);
156 }
157
158
159 static int waitReceive(serial_t* serial, int timeout)
160 {
161   fd_set rfds;
162   struct timeval tv;
163
164   // \83^\83C\83\80\83A\83E\83g\90Ý\92è
165   FD_ZERO(&rfds);
166   FD_SET(serial->fd_, &rfds);
167
168   tv.tv_sec = timeout / 1000;
169   tv.tv_usec = (timeout % 1000) * 1000;
170
171   if (select(serial->fd_ + 1, &rfds, NULL, NULL,
172              (timeout < 0) ? NULL : &tv) <= 0) {
173     /* \83^\83C\83\80\83A\83E\83g\94­\90¶ */
174     return 0;
175   }
176   return 1;
177 }
178
179
180 static int internal_receive(char data[], int data_size_max,
181                             serial_t* serial, int timeout)
182 {
183   int filled = 0;
184
185   if (data_size_max <= 0) {
186     return 0;
187   }
188
189   while (filled < data_size_max) {
190     int require_n;
191     int read_n;
192
193     if (! waitReceive(serial, timeout)) {
194       break;
195     }
196
197     require_n = data_size_max - filled;
198     read_n = read(serial->fd_, &data[filled], require_n);
199     if (read_n <= 0) {
200       /* \93Ç\82Ý\8fo\82µ\83G\83\89\81[\81B\8c»\8dÝ\82Ü\82Å\82Ì\8eó\90M\93à\97e\82Å\96ß\82é */
201       break;
202     }
203     filled += read_n;
204   }
205   return filled;
206 }
207
208
209 /* \8eó\90M */
210 int serial_recv(serial_t *serial, char* data, int data_size_max, int timeout)
211 {
212   int filled;
213   int read_n;
214   int buffer_size;
215
216   if (data_size_max <= 0) {
217     return 0;
218   }
219
220   /* \8f\91\82«\96ß\82µ\82½\82P\95\8e\9a\82ª\82 \82ê\82Î\81A\8f\91\82«\8fo\82· */
221   filled = 0;
222   if (serial->has_last_ch_ != False) {
223     data[0] = serial->last_ch_;
224     serial->has_last_ch_ = False;
225     ++filled;
226   }
227
228   if (! serial_isConnected(serial)) {
229     if (filled > 0) {
230       return filled;
231     }
232     return SerialConnectionFail;
233   }
234
235   buffer_size = ring_size(&serial->ring_);
236   read_n = data_size_max - filled;
237   if (buffer_size < read_n) {
238     // \83\8a\83\93\83O\83o\83b\83t\83@\93à\82Ì\83f\81[\83^\82Å\91«\82è\82È\82¯\82ê\82Î\81A\83f\81[\83^\82ð\93Ç\82Ý\91«\82·
239     char buffer[RingBufferSize];
240     int n = internal_receive(buffer,
241                              ring_capacity(&serial->ring_) - buffer_size,
242                              serial, 0);
243     ring_write(&serial->ring_, buffer, n);
244   }
245   buffer_size = ring_size(&serial->ring_);
246
247   // \83\8a\83\93\83O\83o\83b\83t\83@\93à\82Ì\83f\81[\83^\82ð\95Ô\82·
248   if (read_n > buffer_size) {
249     read_n = buffer_size;
250   }
251   if (read_n > 0) {
252     ring_read(&serial->ring_, &data[filled], read_n);
253     filled += read_n;
254   }
255
256   // \83f\81[\83^\82ð\83^\83C\83\80\83A\83E\83g\95t\82«\82Å\93Ç\82Ý\8fo\82·
257   filled += internal_receive(&data[filled],
258                              data_size_max - filled, serial, timeout);
259   return filled;
260 }
261
262
263 /* \82P\95\8e\9a\8f\91\82«\96ß\82· */
264 void serial_ungetc(serial_t *serial, char ch)
265 {
266   serial->has_last_ch_ = True;
267   serial->last_ch_ = ch;
268 }
269
270
271 void serial_clear(serial_t* serial)
272 {
273   tcdrain(serial->fd_);
274   tcflush(serial->fd_, TCIOFLUSH);
275   ring_clear(&serial->ring_);
276   serial->has_last_ch_ = False;
277 }