/* * Called to set up the serial connection. * * Returns an error message, or NULL on success. * * Also places the canonical host name into `realhost'. It must be * 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) { Serial serial; HANDLE serport; const char *err; serial = snew(struct serial_backend_data); serial->port = INVALID_HANDLE_VALUE; serial->out = serial->in = NULL; serial->bufsize = 0; serial->break_in_progress = FALSE; *backend_handle = serial; serial->frontend = frontend_handle; { char *msg = dupprintf("Opening serial device %s", cfg->serline); logevent(serial->frontend, msg); } serport = CreateFile(cfg->serline, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (serport == INVALID_HANDLE_VALUE) return "Unable to open serial port"; err = serial_configure(serial, serport, cfg); if (err) return err; serial->port = serport; serial->out = handle_output_new(serport, serial_sentdata, serial, HANDLE_FLAG_OVERLAPPED); serial->in = handle_input_new(serport, serial_gotdata, serial, HANDLE_FLAG_OVERLAPPED | HANDLE_FLAG_IGNOREEOF | HANDLE_FLAG_UNITBUFFER); *realhost = dupstr(cfg->serline); /* * Specials are always available. */ update_specials_menu(serial->frontend); return NULL; }
/* * Called to set up the serial connection. * * Returns an error message, or NULL on success. * * Also places the canonical host name into `realhost'. It must be * freed by the caller. */ static const char *serial_init(void *frontend_handle, void **backend_handle, Conf *conf, const char *host, int port, char **realhost, int nodelay, int keepalive) { Serial serial; const char *err; char *line; serial = snew(struct serial_backend_data); *backend_handle = serial; serial->frontend = frontend_handle; serial->finished = FALSE; serial->inbufsize = 0; bufchain_init(&serial->output_data); line = conf_get_str(conf, CONF_serline); { char *msg = dupprintf("Opening serial device %s", line); logevent(serial->frontend, msg); sfree(msg); } serial->fd = open(line, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); if (serial->fd < 0) return "Unable to open serial port"; cloexec(serial->fd); err = serial_configure(serial, conf); if (err) return err; *realhost = dupstr(line); if (!serial_by_fd) serial_by_fd = newtree234(serial_compare_by_fd); add234(serial_by_fd, serial); serial_uxsel_setup(serial); /* * Specials are always available. */ update_specials_menu(serial->frontend); return NULL; }
/* * Called to set up the serial connection. * * Returns an error message, or NULL on success. * * Also places the canonical host name into `realhost'. It must be * freed by the caller. */ static const char *serial_init(void *frontend_handle, void **backend_handle, Conf *conf, const 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; serial->out = serial->in = NULL; serial->bufsize = 0; serial->break_in_progress = FALSE; *backend_handle = serial; serial->frontend = frontend_handle; serline = conf_get_str(conf, CONF_serline); { char *msg = dupprintf("Opening serial device %s", serline); logevent(serial->frontend, msg); sfree(msg); } { /* * 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 * <http://msdn2.microsoft.com/en-us/library/aa365247.aspx> * ("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 <http://msdn2.microsoft.com/en-us/library/aa363858.aspx> * (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, conf); if (err) return err; serial->port = serport; serial->out = handle_output_new(serport, serial_sentdata, serial, HANDLE_FLAG_OVERLAPPED); serial->in = handle_input_new(serport, serial_gotdata, serial, HANDLE_FLAG_OVERLAPPED | HANDLE_FLAG_IGNOREEOF | HANDLE_FLAG_UNITBUFFER); *realhost = dupstr(serline); /* * Specials are always available. */ update_specials_menu(serial->frontend); return NULL; }