fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 269 lines 5.4 kB view raw
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}