fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/drivers/char/char-wincom.c *
7 * Created: 2009-03-07 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2009-2015 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include <stdlib.h>
24
25#include <drivers/options.h>
26#include <drivers/char/char.h>
27#include <drivers/char/char-wincom.h>
28
29#include <windows.h>
30
31
32static
33void chr_wincom_close (char_drv_t *cdrv)
34{
35 char_wincom_t *drv;
36
37 drv = cdrv->ext;
38
39 if (drv->fname != NULL) {
40 free (drv->fname);
41 }
42
43 if (drv->h != INVALID_HANDLE_VALUE) {
44 CloseHandle (drv->h);
45 }
46
47 free (drv);
48}
49
50static
51unsigned chr_wincom_read (char_drv_t *cdrv, void *buf, unsigned cnt)
52{
53 char_wincom_t *drv;
54 DWORD r;
55
56 drv = cdrv->ext;
57
58 if (drv->h == INVALID_HANDLE_VALUE) {
59 return (0);
60 }
61
62 if (ReadFile (drv->h, buf, cnt, &r, NULL) == 0) {
63 return (0);
64 }
65
66 return (r);
67}
68
69static
70unsigned chr_wincom_write (char_drv_t *cdrv, const void *buf, unsigned cnt)
71{
72 char_wincom_t *drv;
73 DWORD r;
74
75 drv = cdrv->ext;
76
77 if (drv->h == INVALID_HANDLE_VALUE) {
78 return (cnt);
79 }
80
81 if (WriteFile (drv->h, buf, cnt, &r, NULL) == 0) {
82 return (0);
83 }
84
85 return (r);
86}
87
88static
89int chr_wincom_set_params (char_drv_t *cdrv, unsigned long bps, unsigned bpc, unsigned parity, unsigned stop)
90{
91 char_wincom_t *drv;
92 DCB dcb;
93
94 drv = cdrv->ext;
95
96 if (drv->h == INVALID_HANDLE_VALUE) {
97 return (0);
98 }
99
100 memset (&dcb, 0, sizeof (dcb));
101 dcb.DCBlength = sizeof (dcb);
102
103 if (GetCommState (drv->h, &dcb) == 0) {
104 return (1);
105 }
106
107 dcb.BaudRate = bps;
108 dcb.ByteSize = bpc;
109
110 switch (stop) {
111 case 1:
112 dcb.StopBits = ONESTOPBIT;
113 break;
114
115 case 2:
116 dcb.StopBits = TWOSTOPBITS;
117 break;
118
119 default:
120 dcb.StopBits = ONESTOPBIT;
121 break;
122 }
123
124 switch (parity) {
125 case 0:
126 dcb.Parity = NOPARITY;
127 break;
128
129 case 1:
130 dcb.Parity = ODDPARITY;
131 break;
132
133 case 2:
134 dcb.Parity = EVENPARITY;
135 break;
136
137 default:
138 dcb.Parity = NOPARITY;
139 break;
140 }
141
142 if (SetCommState (drv->h, &dcb) == 0) {
143 return (1);
144 }
145
146 return (0);
147}
148
149static
150int chr_wincom_get_ctl (char_drv_t *cdrv, unsigned *ctl)
151{
152 char_wincom_t *drv;
153 DWORD val;
154
155 drv = cdrv->ext;
156
157 if (drv->h != INVALID_HANDLE_VALUE) {
158 if (GetCommModemStatus (drv->h, &val) == 0) {
159 return (1);
160 }
161 }
162 else {
163 val = MS_DSR_ON | MS_CTS_ON | MS_RLSD_ON;
164 }
165
166 *ctl = 0;
167 *ctl |= (val & MS_DSR_ON) ? PCE_CHAR_DSR : 0;
168 *ctl |= (val & MS_CTS_ON) ? PCE_CHAR_CTS : 0;
169 *ctl |= (val & MS_RLSD_ON) ? PCE_CHAR_CD : 0;
170 *ctl |= (val & MS_RING_ON) ? PCE_CHAR_RI : 0;
171
172 return (0);
173}
174
175static
176int chr_wincom_set_ctl (char_drv_t *cdrv, unsigned ctl)
177{
178 char_wincom_t *drv;
179
180 drv = cdrv->ext;
181
182 if (drv->h == INVALID_HANDLE_VALUE) {
183 return (0);
184 }
185
186 EscapeCommFunction (drv->h, (ctl & PCE_CHAR_DTR) ? SETDTR : CLRDTR);
187 EscapeCommFunction (drv->h, (ctl & PCE_CHAR_RTS) ? SETRTS : CLRRTS);
188
189 return (0);
190}
191
192static
193int chr_wincom_set_device (char_wincom_t *drv, const char *name)
194{
195 COMMTIMEOUTS to;
196
197 if (drv->h != INVALID_HANDLE_VALUE) {
198 CloseHandle (drv->h);
199 }
200
201 drv->h = CreateFile (name,
202 GENERIC_READ | GENERIC_WRITE,
203 0,
204 NULL,
205 OPEN_EXISTING,
206 0,
207 NULL
208 );
209
210 if (drv->h == INVALID_HANDLE_VALUE) {
211 return (1);
212 }
213
214 GetCommTimeouts (drv->h, &to);
215
216 to.ReadIntervalTimeout = MAXDWORD;
217 to.ReadTotalTimeoutConstant = 0;
218 to.ReadTotalTimeoutMultiplier = 0;
219
220 to.WriteTotalTimeoutConstant = 1;
221 to.WriteTotalTimeoutMultiplier = 0;
222
223 SetCommTimeouts (drv->h, &to);
224
225 return (0);
226}
227
228static
229int chr_wincom_init (char_wincom_t *drv, const char *name)
230{
231 chr_init (&drv->cdrv, drv);
232
233 drv->cdrv.close = chr_wincom_close;
234 drv->cdrv.read = chr_wincom_read;
235 drv->cdrv.write = chr_wincom_write;
236 drv->cdrv.set_params = chr_wincom_set_params;
237 drv->cdrv.get_ctl = chr_wincom_get_ctl;
238 drv->cdrv.set_ctl = chr_wincom_set_ctl;
239
240 drv->fname = drv_get_option (name, "port");
241
242 drv->h = INVALID_HANDLE_VALUE;
243
244 if (drv->fname != NULL) {
245 if (chr_wincom_set_device (drv, drv->fname)) {
246 return (1);
247 }
248 }
249
250 return (0);
251}
252
253char_drv_t *chr_wincom_open (const char *name)
254{
255 char_wincom_t *drv;
256
257 drv = malloc (sizeof (char_wincom_t));
258
259 if (drv == NULL) {
260 return (NULL);
261 }
262
263 if (chr_wincom_init (drv, name)) {
264 free (drv);
265 return (NULL);
266 }
267
268 return (&drv->cdrv);
269}