urg_serial_windows.c
Go to the documentation of this file.
1 
10 #include "urg_c/urg_serial.h"
11 #include <stdio.h>
12 
13 #if defined(URG_MSC)
14 #define False 0
15 #endif
16 
17 
18 static void serial_initialize(urg_serial_t *serial)
19 {
20  serial->hCom = INVALID_HANDLE_VALUE;
21  serial->has_last_ch = False;
22 
24 }
25 
26 
27 static void set_timeout(urg_serial_t *serial, int timeout)
28 {
29  COMMTIMEOUTS timeouts;
30  GetCommTimeouts(serial->hCom, &timeouts);
31 
32  timeouts.ReadIntervalTimeout = (timeout == 0) ? MAXDWORD : 0;
33  timeouts.ReadTotalTimeoutConstant = timeout;
34  timeouts.ReadTotalTimeoutMultiplier = 0;
35 
36  SetCommTimeouts(serial->hCom, &timeouts);
37 }
38 
39 
40 int serial_open(urg_serial_t *serial, const char *device, long baudrate)
41 {
42  // COM10 以降への対応用
43  enum { NameLength = 11 };
44  char adjusted_device[NameLength];
45 
46  serial_initialize(serial);
47 
48  /* COM ポートを開く */
49  _snprintf(adjusted_device, NameLength, "\\\\.\\%s", device);
50  serial->hCom = CreateFileA(adjusted_device, GENERIC_READ | GENERIC_WRITE,
51  0, NULL, OPEN_EXISTING,
52  FILE_ATTRIBUTE_NORMAL, NULL);
53 
54  if (serial->hCom == INVALID_HANDLE_VALUE) {
55  // !!! store error_message buffer
56  //printf("open failed: %s\n", device);
57  return -1;
58  }
59 
60  /* 通信サイズの更新 */
61  SetupComm(serial->hCom, 4096 * 8, 4096);
62 
63  /* ボーレートの変更 */
64  serial_set_baudrate(serial, baudrate);
65 
66  /* シリアル制御構造体の初期化 */
67  serial->has_last_ch = False;
68 
69  /* タイムアウトの設定 */
70  serial->current_timeout = 0;
71  set_timeout(serial, serial->current_timeout);
72 
73  return 0;
74 }
75 
76 
78 {
79  if (serial->hCom != INVALID_HANDLE_VALUE) {
80  CloseHandle(serial->hCom);
81  serial->hCom = INVALID_HANDLE_VALUE;
82  }
83 }
84 
85 
86 int serial_set_baudrate(urg_serial_t *serial, long baudrate)
87 {
88  long baudrate_value;
89  DCB dcb;
90 
91  switch (baudrate) {
92 
93  case 4800:
94  baudrate_value = CBR_4800;
95  break;
96 
97  case 9600:
98  baudrate_value = CBR_9600;
99  break;
100 
101  case 19200:
102  baudrate_value = CBR_19200;
103  break;
104 
105  case 38400:
106  baudrate_value = CBR_38400;
107  break;
108 
109  case 57600:
110  baudrate_value = CBR_57600;
111  break;
112 
113  case 115200:
114  baudrate_value = CBR_115200;
115  break;
116 
117  default:
118  baudrate_value = baudrate;
119  }
120 
121  GetCommState(serial->hCom, &dcb);
122  dcb.BaudRate = baudrate_value;
123  dcb.ByteSize = 8;
124  dcb.Parity = NOPARITY;
125  dcb.fParity = FALSE;
126  dcb.StopBits = ONESTOPBIT;
127  SetCommState(serial->hCom, &dcb);
128 
129  return 0;
130 }
131 
132 
133 int serial_write(urg_serial_t *serial, const char *data, int size)
134 {
135  DWORD n;
136 
137  if (size < 0) {
138  return 0;
139  }
140 
141  if (serial->hCom == INVALID_HANDLE_VALUE) {
142  return -1;
143  }
144 
145  WriteFile(serial->hCom, data, (DWORD)size, &n, NULL);
146  return n;
147 }
148 
149 
150 static int internal_receive(char data[], int max_size,
151  urg_serial_t* serial, int timeout)
152 {
153  int filled = 0;
154  DWORD n;
155 
156  if (timeout != serial->current_timeout) {
157  set_timeout(serial, timeout);
158  serial->current_timeout = timeout;
159  }
160 
161  ReadFile(serial->hCom, &data[filled], (DWORD)max_size - filled, &n, NULL);
162 
163  return filled + n;
164 }
165 
166 
167 int serial_read(urg_serial_t *serial, char *data, int max_size, int timeout)
168 {
169  int filled = 0;
170  int buffer_size;
171  int read_n;
172 
173  if (max_size <= 0) {
174  return 0;
175  }
176 
177  /* 書き戻した1文字があれば、書き出す */
178  if (serial->has_last_ch) {
179  data[0] = serial->last_ch;
180  serial->has_last_ch = False;
181  ++filled;
182  }
183 
184  if (serial->hCom == INVALID_HANDLE_VALUE) {
185  if (filled > 0) {
186  return filled;
187  }
188  return -1;
189  }
190 
191  buffer_size = ring_size(&serial->ring);
192  read_n = max_size - filled;
193  if (buffer_size < read_n) {
194  // リングバッファ内のデータで足りなければ、データを読み足す
195  char buffer[RING_BUFFER_SIZE];
196  int n = internal_receive(buffer,
197  ring_capacity(&serial->ring) - buffer_size,
198  serial, 0);
199  ring_write(&serial->ring, buffer, n);
200  }
201  buffer_size = ring_size(&serial->ring);
202 
203  // リングバッファ内のデータを返す
204  if (read_n > buffer_size) {
205  read_n = buffer_size;
206  }
207  if (read_n > 0) {
208  ring_read(&serial->ring, &data[filled], read_n);
209  filled += read_n;
210  }
211 
212  // データをタイムアウト付きで読み出す
213  filled += internal_receive(&data[filled],
214  max_size - filled, serial, timeout);
215  return filled;
216 }
static int internal_receive(char data[], int max_size, urg_serial_t *serial, int timeout)
シリアル通信用
Definition: urg_serial.h:40
static void set_timeout(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)
データの格納
ring_buffer_t ring
Definition: urg_serial.h:50
char buffer[RING_BUFFER_SIZE]
Definition: urg_serial.h:51
int serial_set_baudrate(urg_serial_t *serial, long baudrate)
ボーレートを設定する
シリアル通信
int ring_read(ring_buffer_t *ring, char *buffer, int size)
データの取り出し
void serial_close(urg_serial_t *serial)
接続を閉じる
char last_ch
Definition: urg_serial.h:53
char has_last_ch
Definition: urg_serial.h:52
int serial_write(urg_serial_t *serial, const char *data, int size)
データを送信する
static void serial_initialize(urg_serial_t *serial)
int serial_open(urg_serial_t *serial, const char *device, long baudrate)
接続を開く
void ring_initialize(ring_buffer_t *ring, char *buffer, const int shift_length)
初期化
int ring_size(const ring_buffer_t *ring)
格納データ数を返す
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