ハードフロー(RTS/CTS)ができるよう修正
- タイムアウト値を修正
- オーバーフロー制御の設定を見直し
- 'v' verbose on/off
- 'D' ダイアログで設定した後、verbose=on時は設定値が表示されるようにした
- 'o' open後、verbose=on時は設定値が表示されるようにした
@@ -103,30 +103,14 @@ | ||
103 | 103 | SetupComm(h, CommInQueSize, CommOutQueSize); |
104 | 104 | PurgeComm(h, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); |
105 | 105 | |
106 | - COMMTIMEOUTS ctmo; | |
107 | - r = GetCommTimeouts(h, &ctmo); | |
108 | - assert(r == TRUE); | |
109 | - printf("Maximum time between read chars %d\n", ctmo.ReadIntervalTimeout); | |
110 | - printf("read Multiplier of characters %d\n", ctmo.ReadTotalTimeoutMultiplier); | |
111 | - printf("read Constant in milliseconds %d\n", ctmo.ReadTotalTimeoutConstant); | |
112 | - printf("write Multiplier of characters %d\n", ctmo.WriteTotalTimeoutMultiplier); | |
113 | - printf("write Constant in milliseconds %d\n", ctmo.WriteTotalTimeoutConstant); | |
114 | - | |
115 | 106 | if (p->commtimeouts_setted) { |
116 | 107 | r = SetCommTimeouts(h, &p->commtimeouts); |
117 | 108 | assert(r == TRUE); |
118 | 109 | } |
119 | - else { | |
120 | - // Tera Term が設定しているパラメータ | |
121 | -#if 0 | |
122 | - memset(&ctmo, 0, sizeof(ctmo)); | |
123 | - ctmo.ReadIntervalTimeout = MAXDWORD; | |
124 | - ctmo.WriteTotalTimeoutConstant = 500; | |
125 | - r = SetCommTimeouts(h, &ctmo); | |
126 | - assert(r == TRUE); | |
127 | -#endif | |
128 | - } | |
129 | 110 | |
111 | + r = GetCommTimeouts(h, &p->commtimeouts); | |
112 | + assert(r == TRUE); | |
113 | + | |
130 | 114 | if (p->dcb_setted) { |
131 | 115 | if (p->dcb.XonChar == p->dcb.XoffChar) { |
132 | 116 | p->dcb.XonChar = 0x11; |
@@ -140,6 +124,9 @@ | ||
140 | 124 | } |
141 | 125 | } |
142 | 126 | |
127 | + r = GetCommState(h, &p->dcb); | |
128 | + assert(r == TRUE); | |
129 | + | |
143 | 130 | SetCommMask(h, 0); |
144 | 131 | SetCommMask(h, EV_RXCHAR); |
145 | 132 |
@@ -451,6 +438,12 @@ | ||
451 | 438 | retval = ERROR_SUCCESS; |
452 | 439 | break; |
453 | 440 | } |
441 | + case GET_COM_DCB: { | |
442 | + DCB *dcb = va_arg(ap, DCB *); | |
443 | + *dcb = p->dcb; | |
444 | + retval = ERROR_SUCCESS; | |
445 | + break; | |
446 | + } | |
454 | 447 | case SET_COM_TIMEOUTS: { |
455 | 448 | COMMTIMEOUTS *commtimeouts = va_arg(ap, COMMTIMEOUTS *); |
456 | 449 | p->commtimeouts = *commtimeouts; |
@@ -458,6 +451,12 @@ | ||
458 | 451 | retval = ERROR_SUCCESS; |
459 | 452 | break; |
460 | 453 | } |
454 | + case GET_COM_TIMEOUTS: { | |
455 | + COMMTIMEOUTS *commtimeouts = va_arg(ap, COMMTIMEOUTS *); | |
456 | + *commtimeouts = p->commtimeouts; | |
457 | + retval = ERROR_SUCCESS; | |
458 | + break; | |
459 | + } | |
461 | 460 | case SET_CHECK_LINE_STATE_BEFORE_SEND: { |
462 | 461 | int check_line_state = va_arg(ap, int); |
463 | 462 | p->check_line_state_before_send = check_line_state; |
@@ -479,6 +478,8 @@ | ||
479 | 478 | if (r == TRUE) { |
480 | 479 | r = SetCommConfig(p->h, &cc, size); |
481 | 480 | assert(r == TRUE); |
481 | + r = GetCommState(p->h, &p->dcb); | |
482 | + assert(r == TRUE); | |
482 | 483 | } |
483 | 484 | break; |
484 | 485 | } |
@@ -37,7 +37,9 @@ | ||
37 | 37 | SET_PORT_NAME, |
38 | 38 | GET_RAW_HANDLE, |
39 | 39 | SET_COM_DCB, |
40 | + GET_COM_DCB, | |
40 | 41 | SET_COM_TIMEOUTS, |
42 | + GET_COM_TIMEOUTS, | |
41 | 43 | SET_CHECK_LINE_STATE_BEFORE_SEND, |
42 | 44 | GET_CHECK_LINE_STATE_BEFORE_SEND, |
43 | 45 | OPEN_CONFIG_DIALOG, |
@@ -41,6 +41,7 @@ | ||
41 | 41 | "'l' disp line state\n" |
42 | 42 | "'L' check line state before sending\n" |
43 | 43 | "'D' open device dialogbox\n" |
44 | + "'v' verbose on/off\n" | |
44 | 45 | " send mode\n" |
45 | 46 | "':' go command mode\n" |
46 | 47 | ); |
@@ -101,6 +102,14 @@ | ||
101 | 102 | printf("Fill for now. %d\n", p->wReserved1); |
102 | 103 | } |
103 | 104 | |
105 | +void dumpCOMMTIMEOUTS(const COMMTIMEOUTS *p) | |
106 | +{ | |
107 | + printf("Maximum time between read chars %d\n", p->ReadIntervalTimeout); | |
108 | + printf("read Multiplier of characters %d\n", p->ReadTotalTimeoutMultiplier); | |
109 | + printf("read Constant in milliseconds %d\n", p->ReadTotalTimeoutConstant); | |
110 | + printf("write Multiplier of characters %d\n", p->WriteTotalTimeoutMultiplier); | |
111 | + printf("write Constant in milliseconds %d\n", p->WriteTotalTimeoutConstant); | |
112 | +} | |
104 | 113 | |
105 | 114 | int wmain(int argc, wchar_t *argv[]) |
106 | 115 | { |
@@ -112,7 +121,7 @@ | ||
112 | 121 | |
113 | 122 | bool verbose = false; |
114 | 123 | wchar_t *ini_base = L"ttcomtester.ini"; |
115 | - int arg_rts = RTS_CONTROL_DISABLE; | |
124 | + const wchar_t *arg_rts = L"off"; | |
116 | 125 | wchar_t *prog = argv[0]; |
117 | 126 | wchar_t *arg_device_name = NULL; |
118 | 127 |
@@ -146,13 +155,13 @@ | ||
146 | 155 | break; |
147 | 156 | case L'r': { |
148 | 157 | if (wcscmp(optarg_w, L"off") == 0) { |
149 | - arg_rts = RTS_CONTROL_DISABLE; | |
158 | + arg_rts = L"off"; | |
150 | 159 | } else if (wcscmp(optarg_w, L"on") == 0) { |
151 | - arg_rts = RTS_CONTROL_ENABLE; | |
160 | + arg_rts = L"on"; | |
152 | 161 | } else if (wcscmp(optarg_w, L"hs") == 0) { |
153 | - arg_rts = RTS_CONTROL_HANDSHAKE; | |
154 | - } else if (wcscmp(optarg_w, L"on") == 0) { | |
155 | - arg_rts = RTS_CONTROL_TOGGLE; | |
162 | + arg_rts = L"hs"; | |
163 | + } else if (wcscmp(optarg_w, L"toggle") == 0) { | |
164 | + arg_rts = L"toggle"; | |
156 | 165 | } else { |
157 | 166 | printf("check rts option"); |
158 | 167 | exit(1); |
@@ -197,25 +206,72 @@ | ||
197 | 206 | |
198 | 207 | device_ope const *ope = dev->ope; |
199 | 208 | ope->ctrl(dev, SET_PORT_NAME, device_name); |
200 | - | |
201 | - DCB dcb; | |
202 | - memset(&dcb, 0, sizeof(dcb)); // 100% buildしてくれないようだ | |
203 | - dcb.DCBlength = sizeof(dcb); | |
204 | - BOOL r = BuildCommDCBW(com_param, &dcb); | |
205 | - dcb.fRtsControl = arg_rts; | |
206 | - if (r == FALSE) { | |
207 | - DWORD e = GetLastError(); | |
208 | - wchar_t b[128]; | |
209 | - swprintf_s(b, _countof(b), L"BuildCommDCBW('%s')", com_param); | |
210 | - DispErrorStr(b, e); | |
211 | - goto finish; | |
212 | - } | |
213 | 209 | if (verbose) { |
214 | 210 | printf("param='%ls'\n", com_param); |
215 | - dumpDCB(&dcb); | |
216 | 211 | } |
217 | - ope->ctrl(dev, SET_COM_DCB, &dcb); | |
218 | 212 | |
213 | + { | |
214 | + DCB dcb; | |
215 | + memset(&dcb, 0, sizeof(dcb)); // 100% buildしてくれないようだ | |
216 | + dcb.DCBlength = sizeof(dcb); | |
217 | + BOOL r = BuildCommDCBW(com_param, &dcb); | |
218 | + if (wcscmp(arg_rts, L"off") == 0) { | |
219 | + dcb.fRtsControl = RTS_CONTROL_DISABLE; | |
220 | + dcb.fOutxCtsFlow = FALSE; | |
221 | + } else if (wcscmp(arg_rts, L"on") == 0) { | |
222 | + dcb.fRtsControl = RTS_CONTROL_ENABLE; | |
223 | + dcb.fOutxCtsFlow = FALSE; | |
224 | + } else if (wcscmp(arg_rts, L"hs") == 0) { | |
225 | + dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; | |
226 | + dcb.fOutxCtsFlow = TRUE; | |
227 | + } else if (wcscmp(arg_rts, L"toggle") == 0) { | |
228 | + dcb.fRtsControl = RTS_CONTROL_TOGGLE; | |
229 | + //dcb.fOutxCtsFlow = TRUE; //?? | |
230 | + } | |
231 | + if (r == FALSE) { | |
232 | + DWORD e = GetLastError(); | |
233 | + wchar_t b[128]; | |
234 | + swprintf_s(b, _countof(b), L"BuildCommDCBW('%s')", com_param); | |
235 | + DispErrorStr(b, e); | |
236 | + goto finish; | |
237 | + } | |
238 | + ope->ctrl(dev, SET_COM_DCB, &dcb); | |
239 | + } | |
240 | + | |
241 | + { | |
242 | + COMMTIMEOUTS timeouts; | |
243 | + memset(&timeouts, 0, sizeof(timeouts)); | |
244 | +#if 0 | |
245 | + // Tera Term が設定しているパラメータ | |
246 | + timeouts.ReadIntervalTimeout = MAXDWORD; | |
247 | + timeouts.WriteTotalTimeoutConstant = 500; | |
248 | +#endif | |
249 | +#if 0 | |
250 | + // CODE PROJECT の値 | |
251 | + // https://www.codeproject.com/articles/3061/creating-a-serial-communication-on-win | |
252 | + timeouts.ReadIntervalTimeout = 3; | |
253 | + timeouts.ReadTotalTimeoutMultiplier = 3; | |
254 | + timeouts.ReadTotalTimeoutConstant = 2; | |
255 | + timeouts.WriteTotalTimeoutMultiplier = 3; | |
256 | + timeouts.WriteTotalTimeoutConstant = 2; | |
257 | +#endif | |
258 | +#if 0 | |
259 | + // PuTTYの値 | |
260 | + timeouts.ReadIntervalTimeout = 1; | |
261 | + timeouts.ReadTotalTimeoutMultiplier = 0; | |
262 | + timeouts.ReadTotalTimeoutConstant = 0; | |
263 | + timeouts.WriteTotalTimeoutMultiplier = 0; | |
264 | + timeouts.WriteTotalTimeoutConstant = 0; | |
265 | +#endif | |
266 | + // 今回提案する値 | |
267 | + timeouts.ReadIntervalTimeout = 1; | |
268 | + timeouts.ReadTotalTimeoutMultiplier = 0; | |
269 | + timeouts.ReadTotalTimeoutConstant = 0; | |
270 | + timeouts.WriteTotalTimeoutMultiplier = 0; | |
271 | + timeouts.WriteTotalTimeoutConstant = 1; | |
272 | + ope->ctrl(dev, SET_COM_TIMEOUTS, &timeouts); | |
273 | + } | |
274 | + | |
219 | 275 | printf( |
220 | 276 | "':' switch mode\n" |
221 | 277 | "' '(space) key usage\n" |
@@ -251,6 +307,14 @@ | ||
251 | 307 | else { |
252 | 308 | DispErrorStr(L"open()", e); |
253 | 309 | } |
310 | + if (verbose) { | |
311 | + DCB dcb; | |
312 | + ope->ctrl(dev, GET_COM_DCB, &dcb); | |
313 | + dumpDCB(&dcb); | |
314 | + COMMTIMEOUTS timeouts; | |
315 | + ope->ctrl(dev, GET_COM_TIMEOUTS, &timeouts); | |
316 | + dumpCOMMTIMEOUTS(&timeouts); | |
317 | + } | |
254 | 318 | break; |
255 | 319 | } |
256 | 320 | case 'c': { |
@@ -266,27 +330,25 @@ | ||
266 | 330 | for(size_t i = 0; i < send_len; i++) { |
267 | 331 | send_data[i] = (unsigned char)i; |
268 | 332 | } |
269 | - size_t sended_len; | |
270 | - DWORD e = ope->write(dev, send_data, send_len, &sended_len); | |
333 | + size_t sent_len; | |
334 | + DWORD e = ope->write(dev, send_data, send_len, &sent_len); | |
271 | 335 | if (e == ERROR_SUCCESS) { |
272 | - printf("sent\n"); | |
336 | + printf("sent %zu bytes\n", sent_len); | |
273 | 337 | } |
274 | 338 | else if (e == ERROR_IO_PENDING) { |
275 | - size_t sended_len_total = sended_len; | |
339 | + size_t sent_len_total = sent_len; | |
276 | 340 | while(1) { |
277 | - r = ope->wait_write(dev, &sended_len); | |
278 | -#if 0 | |
279 | - if (r == ERROR_SUCCESS) { | |
280 | - printf("sent\n"); | |
341 | + DWORD r = ope->wait_write(dev, &sent_len); | |
342 | + if (r != ERROR_SUCCESS) { | |
343 | + printf("send error\n"); | |
281 | 344 | } |
282 | -#endif | |
283 | - sended_len_total += sended_len; | |
284 | - printf("send size %zu(%zu)/%zu\n", sended_len_total, sended_len, send_len); | |
345 | + sent_len_total += sent_len; | |
346 | + printf("send size %zu(%zu)/%zu\n", sent_len_total, sent_len, send_len); | |
285 | 347 | Sleep(100); |
286 | 348 | } |
287 | 349 | } |
288 | 350 | else { |
289 | - DispErrorStr(L"open()", e); | |
351 | + DispErrorStr(L"write()", e); | |
290 | 352 | } |
291 | 353 | free(send_data); |
292 | 354 | break; |
@@ -392,8 +454,18 @@ | ||
392 | 454 | } |
393 | 455 | case 'D': { |
394 | 456 | ope->ctrl(dev, OPEN_CONFIG_DIALOG); |
457 | + if (verbose) { | |
458 | + DCB dcb; | |
459 | + ope->ctrl(dev, GET_COM_DCB, &dcb); | |
460 | + dumpDCB(&dcb); | |
461 | + } | |
395 | 462 | break; |
396 | 463 | } |
464 | + case 'v': { | |
465 | + verbose = verbose ? false : true; | |
466 | + printf("verbose %s\n", verbose?"on":"off"); | |
467 | + break; | |
468 | + } | |
397 | 469 | case ':': { |
398 | 470 | printf("\nsend mode\n"); |
399 | 471 | command_mode = false; |
@@ -413,11 +485,11 @@ | ||
413 | 485 | else { |
414 | 486 | if (state == STATE_OPEN) { |
415 | 487 | char send_text[2]; |
416 | - size_t sended_len; | |
488 | + size_t sent_len; | |
417 | 489 | send_text[0] = (char)c; |
418 | - DWORD e = ope->write(dev, send_text, 1, &sended_len); | |
490 | + DWORD e = ope->write(dev, send_text, 1, &sent_len); | |
419 | 491 | if (e == ERROR_SUCCESS) { |
420 | - printf("send %02x, %zu byte\n", c, sended_len); | |
492 | + printf("send %02x, %zu byte\n", c, sent_len); | |
421 | 493 | } |
422 | 494 | else { |
423 | 495 | DispErrorStr(L"write() error", e); |