urg_serial_linux.c
Go to the documentation of this file.
1 
10 #include "urg_c/urg_ring_buffer.h"
11 #include <fcntl.h>
12 #include <unistd.h>
13 
14 
15 enum {
16  INVALID_FD = -1,
17 };
18 
19 
20 static void serial_initialize(urg_serial_t *serial)
21 {
22  serial->fd = INVALID_FD;
23  serial->has_last_ch = False;
24 
26 }
27 
28 
29 static void serial_clear(urg_serial_t* serial)
30 {
31  tcdrain(serial->fd);
32  tcflush(serial->fd, TCIOFLUSH);
33  ring_clear(&serial->ring);
34  serial->has_last_ch = False;
35 }
36 
37 
38 int serial_open(urg_serial_t *serial, const char *device, long baudrate)
39 {
40  int flags = 0;
41  int ret = 0;
42 
43  serial_initialize(serial);
44 
45 #ifndef URG_MAC_OS
46  enum { O_EXLOCK = 0x0 }; /* Linux では使えないのでダミーを作成しておく */
47 #endif
48  serial->fd = open(device, O_RDWR | O_EXLOCK | O_NONBLOCK | O_NOCTTY);
49  if (serial->fd < 0) {
50  /* 接続に失敗 */
51  //strerror_r(errno, serial->error_string, ERROR_MESSAGE_SIZE);
52  return -1;
53  }
54 
55  flags = fcntl(serial->fd, F_GETFL, 0);
56  fcntl(serial->fd, F_SETFL, flags & ~O_NONBLOCK);
57 
58  /* シリアル通信の初期化 */
59  tcgetattr(serial->fd, &serial->sio);
60  serial->sio.c_iflag = 0;
61  serial->sio.c_oflag = 0;
62  serial->sio.c_cflag &= ~(CSIZE | PARENB | CSTOPB);
63  serial->sio.c_cflag |= CS8 | CREAD | CLOCAL;
64  serial->sio.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN);
65 
66  serial->sio.c_cc[VMIN] = 0;
67  serial->sio.c_cc[VTIME] = 0;
68 
69  /* ボーレートの変更 */
70  ret = serial_set_baudrate(serial, baudrate);
71  if (ret < 0) {
72  return ret;
73  }
74 
75  /* シリアル制御構造体の初期化 */
76  serial->has_last_ch = False;
77 
78  return 0;
79 }
80 
81 
83 {
84  if (serial->fd >= 0) {
85  close(serial->fd);
86  serial->fd = INVALID_FD;
87  }
88 }
89 
90 
91 int serial_set_baudrate(urg_serial_t *serial, long baudrate)
92 {
93  long baudrate_value = -1;
94 
95  switch (baudrate) {
96  case 4800:
97  baudrate_value = B4800;
98  break;
99 
100  case 9600:
101  baudrate_value = B9600;
102  break;
103 
104  case 19200:
105  baudrate_value = B19200;
106  break;
107 
108  case 38400:
109  baudrate_value = B38400;
110  break;
111 
112  case 57600:
113  baudrate_value = B57600;
114  break;
115 
116  case 115200:
117  baudrate_value = B115200;
118  break;
119 
120  default:
121  return -1;
122  }
123 
124  /* ボーレート変更 */
125  cfsetospeed(&serial->sio, baudrate_value);
126  cfsetispeed(&serial->sio, baudrate_value);
127  tcsetattr(serial->fd, TCSADRAIN, &serial->sio);
128  serial_clear(serial);
129 
130  return 0;
131 }
132 
133 
134 int serial_write(urg_serial_t *serial, const char *data, int size)
135 {
136  if (serial->fd == INVALID_FD) {
137  return -1;
138  }
139  return write(serial->fd, data, size);
140 }
141 
142 
143 static int wait_receive(urg_serial_t* serial, int timeout)
144 {
145  fd_set rfds;
146  struct timeval tv;
147 
148  // タイムアウト設定 FD_ZERO(&rfds); FD_SET(serial->fd, &rfds); tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; if (select(serial->fd + 1, &rfds, NULL, NULL, (timeout < 0) ? NULL : &tv) <= 0) { /* タイムアウト発生 */ return 0; } return 1; } static int internal_receive(char data[], int data_size_max, urg_serial_t* serial, int timeout) { int filled = 0; if (data_size_max <= 0) { return 0; } while (filled < data_size_max) { int require_n; int read_n; if (! wait_receive(serial, timeout)) { break; } require_n = data_size_max - filled; read_n = read(serial->fd, &data[filled], require_n); if (read_n <= 0) { /* 読み出しエラー。現在までの受信内容で戻る */ break; } filled += read_n; } return filled; } int serial_read(urg_serial_t *serial, char *data, int max_size, int timeout) { int buffer_size; int read_n; int filled = 0; if (max_size <= 0) { return 0; } /* 書き戻した1文字があれば、書き出す */ if (serial->has_last_ch != False) { data[0] = serial->last_ch; serial->has_last_ch = False; ++filled; } if (serial->fd == INVALID_FD) { if (filled > 0) { return filled; } else { return -1; } } buffer_size = ring_size(&serial->ring); read_n = max_size - filled; if (buffer_size < read_n) { // リングバッファ内のデータで足りなければ、データを読み足す char buffer[RING_BUFFER_SIZE]; int n = internal_receive(buffer, ring_capacity(&serial->ring) - buffer_size, serial, 0); if (n > 0) { ring_write(&serial->ring, buffer, n); buffer_size += n; } } // リングバッファ内のデータを返す if (read_n > buffer_size) { read_n = buffer_size; } if (read_n > 0) { ring_read(&serial->ring, &data[filled], read_n); filled += read_n; } // データをタイムアウト付きで読み出す filled += internal_receive(&data[filled], max_size - filled, serial, timeout); return filled; }
149  FD_ZERO(&rfds);
150  FD_SET(serial->fd, &rfds);
151 
152  tv.tv_sec = timeout / 1000;
153  tv.tv_usec = (timeout % 1000) * 1000;
154 
155  if (select(serial->fd + 1, &rfds, NULL, NULL,
156  (timeout < 0) ? NULL : &tv) <= 0) {
157  /* タイムアウト発生 */
158  return 0;
159  }
160  return 1;
161 }
162 
163 
164 static int internal_receive(char data[], int data_size_max,
165  urg_serial_t* serial, int timeout)
166 {
167  int filled = 0;
168 
169  if (data_size_max <= 0) {
170  return 0;
171  }
172 
173  while (filled < data_size_max) {
174  int require_n;
175  int read_n;
176 
177  if (! wait_receive(serial, timeout)) {
178  break;
179  }
180 
181  require_n = data_size_max - filled;
182  read_n = read(serial->fd, &data[filled], require_n);
183  if (read_n <= 0) {
184  /* 読み出しエラー。現在までの受信内容で戻る */
185  break;
186  }
187  filled += read_n;
188  }
189  return filled;
190 }
191 
192 
193 int serial_read(urg_serial_t *serial, char *data, int max_size, int timeout)
194 {
195  int buffer_size;
196  int read_n;
197  int filled = 0;
198 
199  if (max_size <= 0) {
200  return 0;
201  }
202 
203  /* 書き戻した1文字があれば、書き出す */
204  if (serial->has_last_ch != False) {
205  data[0] = serial->last_ch;
206  serial->has_last_ch = False;
207  ++filled;
208  }
209  if (serial->fd == INVALID_FD) {
210  if (filled > 0) {
211  return filled;
212  } else {
213  return -1;
214  }
215  }
216 
217  buffer_size = ring_size(&serial->ring);
218  read_n = max_size - filled;
219  if (buffer_size < read_n) {
220  // リングバッファ内のデータで足りなければ、データを読み足す
221  char buffer[RING_BUFFER_SIZE];
222  int n = internal_receive(buffer,
223  ring_capacity(&serial->ring) - buffer_size,
224  serial, 0);
225  if (n > 0) {
226  ring_write(&serial->ring, buffer, n);
227  buffer_size += n;
228  }
229  }
230 
231  // リングバッファ内のデータを返す
232  if (read_n > buffer_size) {
233  read_n = buffer_size;
234  }
235  if (read_n > 0) {
236  ring_read(&serial->ring, &data[filled], read_n);
237  filled += read_n;
238  }
239 
240  // データをタイムアウト付きで読み出す
241  filled += internal_receive(&data[filled], max_size - filled,
242  serial, timeout);
243  return filled;
244 }
int serial_write(urg_serial_t *serial, const char *data, int size)
データを送信する
シリアル通信用
Definition: urg_serial.h:40
static int internal_receive(char data[], int data_size_max, urg_serial_t *serial, int timeout)
int ring_capacity(const ring_buffer_t *ring)
最大の格納データ数を返す
int ring_write(ring_buffer_t *ring, const char *data, int size)
データの格納
void serial_close(urg_serial_t *serial)
接続を閉じる
void ring_clear(ring_buffer_t *ring)
リングバッファのクリア
ring_buffer_t ring
Definition: urg_serial.h:50
char buffer[RING_BUFFER_SIZE]
Definition: urg_serial.h:51
リングバッファ
static int wait_receive(urg_serial_t *serial, int timeout)
int ring_read(ring_buffer_t *ring, char *buffer, int size)
データの取り出し
static void serial_initialize(urg_serial_t *serial)
char last_ch
Definition: urg_serial.h:53
char has_last_ch
Definition: urg_serial.h:52
struct termios sio
Definition: urg_serial.h:47
static void serial_clear(urg_serial_t *serial)
void ring_initialize(ring_buffer_t *ring, char *buffer, const int shift_length)
初期化
int ring_size(const ring_buffer_t *ring)
格納データ数を返す
int serial_open(urg_serial_t *serial, const char *device, long baudrate)
接続を開く
int serial_set_baudrate(urg_serial_t *serial, long baudrate)
ボーレートを設定する
int serial_read(urg_serial_t *serial, char *data, int max_size, int timeout)
データを受信する


urg_c
Author(s): Satofumi Kamimura , Katsumi Kimoto, Adrian Boeing
autogenerated on Wed Jun 10 2020 03:48:10