OSDN Git Service

1203d38b9ab8ae812a993eda2a7b80132e9a832e
[kozos-expbrd/kozos_expbrd.git] / firm / hwtest / tools / kz_xmodem / serial_windows.c
1 /**
2  * @file serial_windows.c
3  * @author Shinichiro Nakamura
4  * @brief シリアルポートドライバの実装。(Windowsプラットフォーム用)
5  */
6
7 /*
8  * ===============================================================
9  *  Serial interface library
10  *  Version 0.0.4
11  * ===============================================================
12  * Copyright (c) 2010-2012 Shinichiro Nakamura
13  *
14  * Permission is hereby granted, free of charge, to any person
15  * obtaining a copy of this software and associated documentation
16  * files (the "Software"), to deal in the Software without
17  * restriction, including without limitation the rights to use,
18  * copy, modify, merge, publish, distribute, sublicense, and/or
19  * sell copies of the Software, and to permit persons to whom the
20  * Software is furnished to do so, subject to the following
21  * conditions:
22  *
23  * The above copyright notice and this permission notice shall be
24  * included in all copies or substantial portions of the Software.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
28  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
30  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
31  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33  * OTHER DEALINGS IN THE SOFTWARE.
34  * ===============================================================
35  */
36
37 #include <stdio.h>
38 #include <Windows.h>
39 #include <WinBase.h>
40 #include "serial.h"
41
42 struct serial {
43     char devfile[BUFSIZ];
44     HANDLE handle;
45 };
46
47 /**
48  * シリアルポートをオープンする.
49  *
50  * @param devfile シリアルポートのデバイスファイル名.
51  * @param baud ボーレート.
52  *
53  * @retval !NULL ハンドラ。
54  * @retval NULL 失敗。
55  */
56 SERIAL *serial_open(const char *devfile, const enum SerialBaud baud)
57 {
58     DCB param;
59     int baudrate = 0;
60
61     /*
62      * シリアルデスクリプタの管理領域を確保する.
63      */
64     SERIAL *s = (SERIAL *) malloc(sizeof(SERIAL));
65     if (s == NULL) {
66         return NULL;
67     }
68
69     /*
70      * ポート名を決定する.
71      */
72     if (strstr(devfile, "\\\\.\\") == NULL) {
73         strcpy(s->devfile, "\\\\.\\");
74     } else {
75         strcpy(s->devfile, "");
76     }
77     strcat(s->devfile, devfile);
78
79     /*
80      * ポートを開く.
81      */
82     s->handle = CreateFile(
83             s->devfile,
84             GENERIC_READ | GENERIC_WRITE,
85             0,
86             NULL,
87             OPEN_EXISTING,
88             0,
89             NULL);
90     if (s->handle == INVALID_HANDLE_VALUE) {
91         free(s);
92         return NULL;
93     }
94
95     /*
96      * ポートの設定を行う。
97      */
98     if (!GetCommState(s->handle, &param)) {
99         free(s);
100         return NULL;
101     }
102     switch (baud) {
103     case SerialBaud2400:
104         param.BaudRate = CBR_2400;
105         break;
106     case SerialBaud4800:
107         param.BaudRate = CBR_4800;
108         break;
109     case SerialBaud9600:
110         param.BaudRate = CBR_9600;
111         break;
112     case SerialBaud19200:
113         param.BaudRate = CBR_19200;
114         break;
115     case SerialBaud38400:
116         param.BaudRate = CBR_38400;
117         break;
118     default:
119         param.BaudRate = CBR_9600;
120         break;
121     }
122     param.ByteSize = 8;
123     param.StopBits = ONESTOPBIT;
124     param.Parity = NOPARITY;
125     if(!SetCommState(s->handle, &param)){
126         free(s);
127         return NULL;
128     }
129
130     /*
131      * バッファの内容を捨てる.
132      */
133     PurgeComm(s->handle, PURGE_RXCLEAR);
134     PurgeComm(s->handle, PURGE_TXCLEAR);
135     PurgeComm(s->handle, PURGE_RXABORT);
136     PurgeComm(s->handle, PURGE_TXABORT);
137
138     return s;
139 }
140
141 /**
142  * シリアルポートをクローズする.
143  *
144  * @param s シリアルデスクリプタへのポインタ.
145  *
146  * @return 成功したら0を返す.
147  */
148 int serial_close(SERIAL * s)
149 {
150
151     /*
152      * バッファの内容を捨てる.
153      */
154     PurgeComm(s->handle, PURGE_RXCLEAR);
155     PurgeComm(s->handle, PURGE_TXCLEAR);
156     PurgeComm(s->handle, PURGE_RXABORT);
157     PurgeComm(s->handle, PURGE_TXABORT);
158
159     /*
160      * ポートを閉じる.
161      */
162     CloseHandle(s->handle);
163
164     /*
165      * シリアルデスクリプタの管理領域を破棄する.
166      */
167     free(s);
168
169     return 0;
170 }
171
172 /**
173  * シリアルポートから指定バイト数の読み込みを実行する.
174  *
175  * @param s シリアルデスクリプタへのポインタ.
176  * @param buf バッファへのポインタ.
177  * @param size 読み込みバイト数.
178  *
179  * @return 成功したら0を返す.
180  */
181 int serial_read(SERIAL * s, unsigned char *buf, const size_t size)
182 {
183     int e = 0;
184     DWORD cnt;
185
186     /*
187      * 読み込みを実行する.
188      */
189     if(!ReadFile(s->handle, buf, size, &cnt, NULL)){
190         e = 1;
191     }
192
193     return e;
194 }
195
196 /**
197  * シリアルポートから指定バイト数の読み込みを実行する.
198  *
199  * @param s シリアルデスクリプタへのポインタ.
200  * @param buf バッファへのポインタ.
201  * @param size 読み込みバイト数.
202  * @param ms ミリ秒単位のタイムアウト時間.
203  *
204  * @return 成功したら0を返す.
205  */
206 int serial_read_with_timeout(SERIAL * s,
207         unsigned char *buf, const size_t size, const int ms)
208 {
209     int e = 0;
210     DWORD total = 0;
211
212     /*
213      * タイムアウトを設定して読み込みを実行する.
214      */
215     COMMTIMEOUTS cto;
216     cto.ReadIntervalTimeout = MAXDWORD;
217     cto.ReadTotalTimeoutConstant = ms;
218     cto.ReadTotalTimeoutMultiplier = MAXDWORD;
219     if(SetCommTimeouts(s->handle, &cto)){
220         /*
221          * 読み込みを実行する.
222          */
223         while (total < size) {
224             DWORD cnt = 0;
225             ReadFile(s->handle, buf + total, 1, &cnt, NULL);
226             if (cnt != 1) {
227                 e = 2;
228                 break;
229             }
230             total += cnt;
231         }
232     } else {
233         /*
234          * タイムアウトの設定に失敗した。
235          */
236         e = 1;
237     }
238
239     return e;
240 }
241
242 /**
243  * シリアルポートへ指定バイト数の書き込みを実行する.
244  *
245  * @param s シリアルデスクリプタへのポインタ.
246  * @param buf バッファへのポインタ.
247  * @param size 書き込みバイト数.
248  *
249  * @return 成功したら0を返す.
250  */
251 int serial_write(SERIAL * s,
252         const unsigned char *buf, const size_t size)
253 {
254     int e = 0;
255     DWORD cnt;
256
257     /*
258      * 書き込みを実行する.
259      */
260     if(!WriteFile(s->handle, buf, size, &cnt, NULL)){
261         e = 1;
262     }
263
264     return e;
265 }
266