]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/hokuyo/lib/serial_ctrl_win.c
Add unified ORTE topic type for LIDAR scan data
[eurobot/public.git] / src / hokuyo / lib / serial_ctrl_win.c
1 /*!\r
2   \file\r
3   \brief \83V\83\8a\83A\83\8b\92Ê\90M (Windows \8eÀ\91\95)\r
4 \r
5   Serial Communication Interface \90§\8cä\r
6 \r
7   \author Satofumi KAMIMURA\r
8 \r
9   $Id: serial_ctrl_win.c 1559 2009-12-01 13:13:08Z satofumi $\r
10 */\r
11 \r
12 #include "serial_ctrl.h"\r
13 #include "serial_errno.h"\r
14 #include "ring_buffer.h"\r
15 #include <stdio.h>\r
16 \r
17 \r
18 enum {\r
19   False = 0,\r
20   True,\r
21 };\r
22 \r
23 \r
24 static void setTimeout(serial_t *serial, int timeout)\r
25 {\r
26   COMMTIMEOUTS timeouts;\r
27   GetCommTimeouts(serial->hCom_, &timeouts);\r
28 \r
29   timeouts.ReadIntervalTimeout = (timeout == 0) ? MAXDWORD : 0;\r
30   timeouts.ReadTotalTimeoutConstant = timeout;\r
31   timeouts.ReadTotalTimeoutMultiplier = 0;\r
32 \r
33   SetCommTimeouts(serial->hCom_, &timeouts);\r
34 }\r
35 \r
36 \r
37 void serial_initialize(serial_t *serial)\r
38 {\r
39   serial->hCom_ = INVALID_HANDLE_VALUE;\r
40   serial->errno_ = SerialNoError;\r
41   serial->has_last_ch_ = False;\r
42 \r
43   ring_initialize(&serial->ring_, serial->buffer_, RingBufferSizeShift);\r
44 }\r
45 \r
46 \r
47 /* \90Ú\91± */\r
48 int serial_connect(serial_t *serial, const char *device, long baudrate)\r
49 {\r
50   // COM10 \88È\8d~\82Ö\82Ì\91Î\89\9e\97p\r
51   enum { NameLength = 11 };\r
52   char adjusted_device[NameLength];\r
53 \r
54   serial_initialize(serial);\r
55 \r
56   /* COM \83|\81[\83g\82ð\8aJ\82­ */\r
57   _snprintf(adjusted_device, NameLength, "\\\\.\\%s", device);\r
58   serial->hCom_ = CreateFileA(adjusted_device, GENERIC_READ | GENERIC_WRITE, 0,\r
59                               NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\r
60 \r
61   if (serial->hCom_ == INVALID_HANDLE_VALUE) {\r
62     printf("open failed: %s\n", device);\r
63     return -1;\r
64   }\r
65 \r
66   /* \92Ê\90M\83T\83C\83Y\82Ì\8dX\90V */\r
67   SetupComm(serial->hCom_, 4096 * 8, 4096);\r
68 \r
69   /* \83{\81[\83\8c\81[\83g\82Ì\95Ï\8dX */\r
70   serial_setBaudrate(serial, baudrate);\r
71 \r
72   /* \83V\83\8a\83A\83\8b\90§\8cä\8d\\91¢\91Ì\82Ì\8f\89\8aú\89» */\r
73   serial->has_last_ch_ = False;\r
74 \r
75   /* \83^\83C\83\80\83A\83E\83g\82Ì\90Ý\92è */\r
76   serial->current_timeout_ = 0;\r
77   setTimeout(serial, serial->current_timeout_);\r
78 \r
79   return 0;\r
80 }\r
81 \r
82 \r
83 /* \90Ø\92f */\r
84 void serial_disconnect(serial_t *serial)\r
85 {\r
86   if (serial->hCom_ != INVALID_HANDLE_VALUE) {\r
87     CloseHandle(serial->hCom_);\r
88     serial->hCom_ = INVALID_HANDLE_VALUE;\r
89   }\r
90 }\r
91 \r
92 \r
93 int serial_isConnected(const serial_t *serial)\r
94 {\r
95   return (serial->hCom_ == INVALID_HANDLE_VALUE) ? 0 : 1;\r
96 }\r
97 \r
98 \r
99 /* \83{\81[\83\8c\81[\83g\82Ì\95Ï\8dX */\r
100 int serial_setBaudrate(serial_t *serial, long baudrate)\r
101 {\r
102   long baudrate_value;\r
103   DCB dcb;\r
104 \r
105   switch (baudrate) {\r
106 \r
107   case 4800:\r
108     baudrate_value = CBR_4800;\r
109     break;\r
110 \r
111   case 9600:\r
112     baudrate_value = CBR_9600;\r
113     break;\r
114 \r
115   case 19200:\r
116     baudrate_value = CBR_19200;\r
117     break;\r
118 \r
119   case 38400:\r
120     baudrate_value = CBR_38400;\r
121     break;\r
122 \r
123   case 57600:\r
124     baudrate_value = CBR_57600;\r
125     break;\r
126 \r
127   case 115200:\r
128     baudrate_value = CBR_115200;\r
129     break;\r
130 \r
131   default:\r
132     baudrate_value = baudrate;\r
133   }\r
134 \r
135   GetCommState(serial->hCom_, &dcb);\r
136   dcb.BaudRate = baudrate_value;\r
137   dcb.ByteSize = 8;\r
138   dcb.Parity = NOPARITY;\r
139   dcb.fParity = FALSE;\r
140   dcb.StopBits = ONESTOPBIT;\r
141   SetCommState(serial->hCom_, &dcb);\r
142 \r
143   return 0;\r
144 }\r
145 \r
146 \r
147 /* \91\97\90M */\r
148 int serial_send(serial_t *serial, const char *data, int data_size)\r
149 {\r
150   DWORD n;\r
151 \r
152   if (data_size < 0) {\r
153     return 0;\r
154   }\r
155 \r
156   if (! serial_isConnected(serial)) {\r
157     return SerialConnectionFail;\r
158   }\r
159 \r
160   WriteFile(serial->hCom_, data, (DWORD)data_size, &n, NULL);\r
161   return n;\r
162 }\r
163 \r
164 \r
165 static int internal_receive(char data[], int data_size_max,\r
166                             serial_t* serial, int timeout)\r
167 {\r
168   int filled = 0;\r
169   DWORD n;\r
170 \r
171   if (timeout != serial->current_timeout_) {\r
172     setTimeout(serial, timeout);\r
173     serial->current_timeout_ = timeout;\r
174   }\r
175 \r
176   ReadFile(serial->hCom_, &data[filled],\r
177            (DWORD)data_size_max - filled, &n, NULL);\r
178 \r
179   return filled + n;\r
180 }\r
181 \r
182 \r
183 /* \8eó\90M */\r
184 int serial_recv(serial_t *serial, char* data, int data_size_max, int timeout)\r
185 {\r
186   int filled = 0;\r
187   int buffer_size;\r
188   int read_n;\r
189 \r
190   if (data_size_max <= 0) {\r
191     return 0;\r
192   }\r
193 \r
194   /* \8f\91\82«\96ß\82µ\82½\82P\95\8e\9a\82ª\82 \82ê\82Î\81A\8f\91\82«\8fo\82· */\r
195   if (serial->has_last_ch_) {\r
196     data[0] = serial->last_ch_;\r
197     serial->has_last_ch_ = False;\r
198     ++filled;\r
199   }\r
200 \r
201   if (! serial_isConnected(serial)) {\r
202     if (filled > 0) {\r
203       return filled;\r
204     }\r
205     return SerialConnectionFail;\r
206   }\r
207 \r
208   buffer_size = ring_size(&serial->ring_);\r
209   read_n = data_size_max - filled;\r
210   if (buffer_size < read_n) {\r
211     // \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·\r
212     char buffer[RingBufferSize];\r
213     int n = internal_receive(buffer,\r
214                              ring_capacity(&serial->ring_) - buffer_size,\r
215                              serial, 0);\r
216     ring_write(&serial->ring_, buffer, n);\r
217   }\r
218   buffer_size = ring_size(&serial->ring_);\r
219 \r
220   // \83\8a\83\93\83O\83o\83b\83t\83@\93à\82Ì\83f\81[\83^\82ð\95Ô\82·\r
221   if (read_n > buffer_size) {\r
222     read_n = buffer_size;\r
223   }\r
224   if (read_n > 0) {\r
225     ring_read(&serial->ring_, &data[filled], read_n);\r
226     filled += read_n;\r
227   }\r
228 \r
229   // \83f\81[\83^\82ð\83^\83C\83\80\83A\83E\83g\95t\82«\82Å\93Ç\82Ý\8fo\82·\r
230   filled += internal_receive(&data[filled],\r
231                              data_size_max - filled, serial, timeout);\r
232   return filled;\r
233 }\r
234 \r
235 \r
236 /* \82P\95\8e\9a\8f\91\82«\96ß\82· */\r
237 void serial_ungetc(serial_t *serial, char ch)\r
238 {\r
239   serial->has_last_ch_ = True;\r
240   serial->last_ch_ = ch;\r
241 }\r
242 \r
243 \r
244 void serial_clear(serial_t* serial)\r
245 {\r
246   PurgeComm(serial->hCom_,\r
247             PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR);\r
248 \r
249   serial->has_last_ch_ = False;\r
250 }\r