Develop and Download Open Source Software

Browse Subversion Repository

Contents of /connection/SerialCtrl_win.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 288 - (show annotations) (download) (as text)
Tue Mar 18 00:09:55 2008 UTC (16 years ago) by satofumi
File MIME type: text/x-c++src
File size: 5098 byte(s)
COM の文字を ASCII で認識するように修正。
1 /*!
2 \file
3 \brief シリアル接続 (Windows)
4
5 \author Satofumi KAMIMURA
6 \author Tomoaki YOSHIDA
7
8 $Id$
9 */
10
11 #include "SerialCtrl.h"
12 #include "RingBuffer.h"
13 #include <errno.h>
14 #include <windows.h>
15
16 using namespace beego;
17
18
19 /*!
20 \brief SerialCtrl の内部クラス
21 */
22 struct SerialCtrl::pImpl {
23 std::string error_message;
24 RingBuffer<char> ring_buffer;
25 HANDLE hComm;
26
27 pImpl(void) : error_message("Not connected."), hComm(INVALID_HANDLE_VALUE) {
28 }
29
30 ~pImpl(void) {
31 disconnect();
32 }
33
34 void disconnect(void) {
35 if (hComm != INVALID_HANDLE_VALUE) {
36 CloseHandle(hComm);
37 hComm = INVALID_HANDLE_VALUE;
38 }
39 }
40
41 bool changeBaudrate(long baudrate) {
42
43 DCB dcb;
44 GetCommState(hComm, &dcb);
45 dcb.BaudRate = baudrate;
46 dcb.ByteSize = 8;
47 dcb.Parity = NOPARITY;
48 dcb.fParity = FALSE;
49 dcb.StopBits = ONESTOPBIT;
50 SetCommState(hComm, &dcb);
51
52 return true;
53 }
54
55 void update(int timeout, int size = 0) {
56
57 int filled = 0;
58 int readable_size = 0;
59
60 // 存在するデータの読み出し
61 enum { BufferSize = 1024 };
62 char data[BufferSize];
63
64 do {
65 DWORD dwErrors;
66 COMSTAT ComStat;
67 ClearCommError(hComm, &dwErrors, &ComStat);
68 readable_size = (int)ComStat.cbInQue;
69 int read_n = (readable_size > BufferSize) ? BufferSize : readable_size;
70
71 DWORD n;
72 ReadFile(hComm, data, read_n, &n, NULL);
73 ring_buffer.put(data, n);
74
75 filled += n;
76 readable_size -= n;
77
78 if (filled >= size) {
79 return;
80 }
81 } while (readable_size > 0);
82
83 if (timeout > 0) {
84 // 受信タイムアウトを評価しつつ、データ受信を行う
85 COMMTIMEOUTS pcto;
86 GetCommTimeouts(hComm, &pcto);
87 pcto.ReadIntervalTimeout = 0;
88 pcto.ReadTotalTimeoutMultiplier = 0;
89 pcto.ReadTotalTimeoutConstant = timeout;
90 SetCommTimeouts(hComm, &pcto);
91
92 // データの読み出しは、1文字ずつ行う
93 DWORD n;
94 while (1) {
95 ReadFile(hComm, data, 1, &n, NULL);
96 if (n < 1) {
97 return;
98 }
99 ring_buffer.put(data, n);
100 filled += n;
101 if (filled >= size) {
102 return;
103 }
104 }
105 }
106 }
107 };
108
109
110 SerialCtrl::SerialCtrl(void) : pimpl(new pImpl) {
111 }
112
113
114 SerialCtrl::~SerialCtrl(void) {
115 }
116
117
118 const char* SerialCtrl::what(void) {
119 return pimpl->error_message.c_str();
120 }
121
122
123 bool SerialCtrl::connect(const char* device, long baudrate) {
124
125 // 接続
126 if (strlen(device) >= 6) {
127 // 無効なデバイス名とみなす
128 // !!! エラー状態を更新すべき
129 return false;
130 }
131 char adjust_device[16];
132 sprintf(adjust_device, "\\\\.\\%s", device);
133 pimpl->hComm = CreateFileA(adjust_device, GENERIC_READ | GENERIC_WRITE, 0,
134 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
135
136 if (pimpl->hComm == INVALID_HANDLE_VALUE) {
137 #if 0
138 LPVOID lpMsg;
139 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
140 FORMAT_MESSAGE_FROM_SYSTEM |
141 FORMAT_MESSAGE_IGNORE_INSERTS,
142 NULL, GetLastError(),
143 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
144 (LPTSTR)&lpMsg, 0, NULL);
145 #endif
146 char buffer[256];
147
148 //DWORD error = GetLastError();
149 // !!! lpMsg の使い方を確認し、いずれ取り込む
150 //sprintf(buffer, "port(%s) open failed: %s\n", device); //, lpMsg);
151 sprintf(buffer, "port(%s) open failed\n", device); //, lpMsg);
152 pimpl->error_message = buffer;
153 //LocalFree(lpMsg);
154 return false;
155 }
156
157 // ボーレート設定
158 bool ret = pimpl->changeBaudrate(baudrate);
159 if (ret == false) {
160 return false;
161 }
162 pimpl->error_message = "no error";
163
164 return true;
165 }
166
167
168 void SerialCtrl::disconnect(void) {
169 pimpl->disconnect();
170 }
171
172
173 bool SerialCtrl::isConnected(void) {
174 return (pimpl->hComm == INVALID_HANDLE_VALUE) ? false : true;
175 }
176
177
178 bool SerialCtrl::changeBaudrate(long baudrate) {
179 return pimpl->changeBaudrate(baudrate);
180 }
181
182
183 int SerialCtrl::send(const char* data, int size) {
184 if (isConnected() == false) {
185 return 0;
186 }
187
188 DWORD n;
189 WriteFile(pimpl->hComm, data, size, &n, NULL);
190 return n;
191 }
192
193
194 int SerialCtrl::recv(char* data, int size, int timeout) {
195 if ((isConnected() == false) || (size <= 0)) {
196 return 0;
197 }
198
199 // 要求分だけ受信データがあれば、返す
200 int filled = SerialCtrl::size();
201 if (filled >= size) {
202 pimpl->ring_buffer.get(data, size);
203 return size;
204 }
205
206 // 受信できたデータを返す
207 int left = size - filled;
208 pimpl->update(timeout, left);
209
210 // size() を呼ぶと update(0) が呼ばれるため
211 filled = pimpl->ring_buffer.size();
212 pimpl->ring_buffer.get(data, filled);
213
214 return filled;
215 }
216
217
218 int SerialCtrl::size(int timeout) {
219 pimpl->update(timeout);
220 return pimpl->ring_buffer.size();
221 }
222
223
224 void SerialCtrl::clear(void) {
225 pimpl->update(0);
226 pimpl->ring_buffer.clear();
227 }
228
229
230 void SerialCtrl::skip(int timeout) {
231 clear();
232
233 char buffer[BUFSIZ];
234 int total = 0;
235 int n;
236
237 enum { EachTimeout = 10 };
238 do {
239 n = recv(buffer, BUFSIZ, EachTimeout);
240 total += EachTimeout;
241 } while ((n > 0) && ((timeout > 0) && (total < timeout)));
242 }
243
244
245 void SerialCtrl::flush(void) {
246 FlushFileBuffers(pimpl->hComm);
247 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26