X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/4a0b6d6164ce80aa9c7b160080e2995eec2fa2ce..8d90b8b27bf086da6245030459ab3e5977313eb0:/windows/winser.c diff --git a/windows/winser.c b/windows/winser.c index cd31b5af..086d3e5c 100644 --- a/windows/winser.c +++ b/windows/winser.c @@ -87,7 +87,7 @@ static void serial_sentdata(struct handle *h, int new_backlog) } } -static const char *serial_configure(Serial serial, HANDLE serport, Config *cfg) +static const char *serial_configure(Serial serial, HANDLE serport, Conf *conf) { DCB dcb; COMMTIMEOUTS timeouts; @@ -121,17 +121,17 @@ static const char *serial_configure(Serial serial, HANDLE serport, Config *cfg) /* * Configurable parameters. */ - dcb.BaudRate = cfg->serspeed; - msg = dupprintf("Configuring baud rate %d", cfg->serspeed); + dcb.BaudRate = conf_get_int(conf, CONF_serspeed); + msg = dupprintf("Configuring baud rate %d", dcb.BaudRate); logevent(serial->frontend, msg); sfree(msg); - dcb.ByteSize = cfg->serdatabits; - msg = dupprintf("Configuring %d data bits", cfg->serdatabits); + dcb.ByteSize = conf_get_int(conf, CONF_serdatabits); + msg = dupprintf("Configuring %d data bits", dcb.ByteSize); logevent(serial->frontend, msg); sfree(msg); - switch (cfg->serstopbits) { + switch (conf_get_int(conf, CONF_serstopbits)) { case 2: dcb.StopBits = ONESTOPBIT; str = "1"; break; case 3: dcb.StopBits = ONE5STOPBITS; str = "1.5"; break; case 4: dcb.StopBits = TWOSTOPBITS; str = "2"; break; @@ -141,7 +141,7 @@ static const char *serial_configure(Serial serial, HANDLE serport, Config *cfg) logevent(serial->frontend, msg); sfree(msg); - switch (cfg->serparity) { + switch (conf_get_int(conf, CONF_serparity)) { case SER_PAR_NONE: dcb.Parity = NOPARITY; str = "no"; break; case SER_PAR_ODD: dcb.Parity = ODDPARITY; str = "odd"; break; case SER_PAR_EVEN: dcb.Parity = EVENPARITY; str = "even"; break; @@ -152,7 +152,7 @@ static const char *serial_configure(Serial serial, HANDLE serport, Config *cfg) logevent(serial->frontend, msg); sfree(msg); - switch (cfg->serflow) { + switch (conf_get_int(conf, CONF_serflow)) { case SER_FLOW_NONE: str = "no"; break; @@ -199,13 +199,13 @@ static const char *serial_configure(Serial serial, HANDLE serport, Config *cfg) * freed by the caller. */ static const char *serial_init(void *frontend_handle, void **backend_handle, - Config *cfg, - char *host, int port, char **realhost, int nodelay, - int keepalive) + Conf *conf, char *host, int port, + char **realhost, int nodelay, int keepalive) { Serial serial; HANDLE serport; const char *err; + char *serline; serial = snew(struct serial_backend_data); serial->port = INVALID_HANDLE_VALUE; @@ -216,17 +216,47 @@ static const char *serial_init(void *frontend_handle, void **backend_handle, serial->frontend = frontend_handle; + serline = conf_get_str(conf, CONF_serline); { - char *msg = dupprintf("Opening serial device %s", cfg->serline); + char *msg = dupprintf("Opening serial device %s", serline); logevent(serial->frontend, msg); } - serport = CreateFile(cfg->serline, GENERIC_READ | GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + { + /* + * Munge the string supplied by the user into a Windows filename. + * + * Windows supports opening a few "legacy" devices (including + * COM1-9) by specifying their names verbatim as a filename to + * open. (Thus, no files can ever have these names. See + * + * ("Naming a File") for the complete list of reserved names.) + * + * However, this doesn't let you get at devices COM10 and above. + * For that, you need to specify a filename like "\\.\COM10". + * This is also necessary for special serial and serial-like + * devices such as \\.\WCEUSBSH001. It also works for the "legacy" + * names, so you can do \\.\COM1 (verified as far back as Win95). + * See + * (CreateFile() docs). + * + * So, we believe that prepending "\\.\" should always be the + * Right Thing. However, just in case someone finds something to + * talk to that doesn't exist under there, if the serial line + * contains a backslash, we use it verbatim. (This also lets + * existing configurations using \\.\ continue working.) + */ + char *serfilename = + dupprintf("%s%s", strchr(serline, '\\') ? "" : "\\\\.\\", serline); + serport = CreateFile(serfilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + sfree(serfilename); + } + if (serport == INVALID_HANDLE_VALUE) return "Unable to open serial port"; - err = serial_configure(serial, serport, cfg); + err = serial_configure(serial, serport, conf); if (err) return err; @@ -238,7 +268,7 @@ static const char *serial_init(void *frontend_handle, void **backend_handle, HANDLE_FLAG_IGNOREEOF | HANDLE_FLAG_UNITBUFFER); - *realhost = dupstr(cfg->serline); + *realhost = dupstr(serline); /* * Specials are always available. @@ -257,12 +287,12 @@ static void serial_free(void *handle) sfree(serial); } -static void serial_reconfig(void *handle, Config *cfg) +static void serial_reconfig(void *handle, Conf *conf) { Serial serial = (Serial) handle; const char *err; - err = serial_configure(serial, serial->port, cfg); + err = serial_configure(serial, serial->port, conf); /* * FIXME: what should we do if err returns something? @@ -301,11 +331,11 @@ static void serial_size(void *handle, int width, int height) return; } -static void serbreak_timer(void *ctx, long now) +static void serbreak_timer(void *ctx, unsigned long now) { Serial serial = (Serial)ctx; - if (now >= serial->clearbreak_time && serial->port) { + if (now == serial->clearbreak_time && serial->port) { ClearCommBreak(serial->port); serial->break_in_progress = FALSE; logevent(serial->frontend, "Finished serial break"); @@ -423,5 +453,7 @@ Backend serial_backend = { serial_provide_logctx, serial_unthrottle, serial_cfg_info, - 1 + "serial", + PROT_SERIAL, + 0 };