1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-03-20 05:45:27 -05:00
putty-source/sercfg.c
Simon Tatham 34f747421d Support for Windows PuTTY connecting straight to a local serial port
in place of making a network connection. This has involved a couple
of minor infrastructure changes:
 - New dlg_label_change() function in the dialog.h interface, which
   alters the label on a control. Only used, at present, to switch
   the Host Name and Port boxes into Serial Line and Speed, which
   means that any platform not implementing serial connections (i.e.
   currently all but Windows) does not need to actually do anything
   in this function. Yet.
 - New small piece of infrastructure: cfg_launchable() determines
   whether a Config structure describes a session ready to be
   launched. This was previously determined by seeing if it had a
   non-empty host name, but it has to check the serial line as well
   so there's a centralised function for it. I haven't gone through
   all front ends and arranged for this function to be used
   everywhere it needs to be; so far I've only checked Windows.
 - Similarly, cfg_dest() returns the destination of a connection
   (host name or serial line) in a text format suitable for putting
   into messages such as `Unable to connect to %s'.

[originally from svn r6815]
2006-08-28 10:35:12 +00:00

168 lines
4.9 KiB
C

/*
* sercfg.c - the serial-port specific parts of the PuTTY
* configuration box. Centralised as cross-platform code because
* more than one platform will want to use it, but not part of the
* main configuration. The expectation is that each platform's
* local config function will call out to ser_setup_config_box() if
* it needs to set up the standard serial stuff. (Of course, it can
* then apply local tweaks after ser_setup_config_box() returns, if
* it needs to.)
*/
#include <assert.h>
#include <stdlib.h>
#include "putty.h"
#include "dialog.h"
#include "storage.h"
static void serial_parity_handler(union control *ctrl, void *dlg,
void *data, int event)
{
static const struct {
const char *name;
int val;
} parities[] = {
{"None", SER_PAR_NONE},
{"Odd", SER_PAR_ODD},
{"Even", SER_PAR_EVEN},
{"Mark", SER_PAR_MARK},
{"Space", SER_PAR_SPACE},
};
int i;
Config *cfg = (Config *)data;
if (event == EVENT_REFRESH) {
dlg_update_start(ctrl, dlg);
dlg_listbox_clear(ctrl, dlg);
for (i = 0; i < lenof(parities); i++)
dlg_listbox_addwithid(ctrl, dlg, parities[i].name,
parities[i].val);
for (i = 0; i < lenof(parities); i++)
if (cfg->serparity == parities[i].val)
dlg_listbox_select(ctrl, dlg, i);
dlg_update_done(ctrl, dlg);
} else if (event == EVENT_SELCHANGE) {
int i = dlg_listbox_index(ctrl, dlg);
if (i < 0)
i = SER_PAR_NONE;
else
i = dlg_listbox_getid(ctrl, dlg, i);
cfg->serparity = i;
}
}
static void serial_flow_handler(union control *ctrl, void *dlg,
void *data, int event)
{
static const struct {
const char *name;
int val;
} flows[] = {
{"None", SER_FLOW_NONE},
{"XON/XOFF", SER_FLOW_XONXOFF},
{"RTS/CTS", SER_FLOW_RTSCTS},
{"DSR/DTR", SER_FLOW_DSRDTR},
};
int i;
Config *cfg = (Config *)data;
if (event == EVENT_REFRESH) {
dlg_update_start(ctrl, dlg);
dlg_listbox_clear(ctrl, dlg);
for (i = 0; i < lenof(flows); i++)
dlg_listbox_addwithid(ctrl, dlg, flows[i].name,
flows[i].val);
for (i = 0; i < lenof(flows); i++)
if (cfg->serflow == flows[i].val)
dlg_listbox_select(ctrl, dlg, i);
dlg_update_done(ctrl, dlg);
} else if (event == EVENT_SELCHANGE) {
int i = dlg_listbox_index(ctrl, dlg);
if (i < 0)
i = SER_PAR_NONE;
else
i = dlg_listbox_getid(ctrl, dlg, i);
cfg->serflow = i;
}
}
void ser_setup_config_box(struct controlbox *b, int midsession)
{
struct controlset *s;
union control *c;
/*
* Add the serial back end to the protocols list at the top of
* the config box.
*/
s = ctrl_getset(b, "Session", "hostport",
"Specify your connection by host name or IP address");
{
int i;
extern void config_protocolbuttons_handler(union control *, void *,
void *, int);
for (i = 0; i < s->ncontrols; i++) {
c = s->ctrls[i];
if (c->generic.type == CTRL_RADIO &&
c->generic.handler == config_protocolbuttons_handler) {
c->radio.nbuttons++;
c->radio.ncolumns++;
c->radio.buttons =
sresize(c->radio.buttons, c->radio.nbuttons, char *);
c->radio.buttons[c->radio.nbuttons-1] =
dupstr("Serial");
c->radio.buttondata =
sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
c->radio.buttondata[c->radio.nbuttons-1] = I(PROT_SERIAL);
if (c->radio.shortcuts) {
c->radio.shortcuts =
sresize(c->radio.shortcuts, c->radio.nbuttons, char);
c->radio.shortcuts[c->radio.nbuttons-1] = NO_SHORTCUT;
}
}
}
}
/*
* Entirely new Connection/Serial panel for serial port
* configuration.
*/
ctrl_settitle(b, "Connection/Serial",
"Options controlling local serial lines");
if (!midsession) {
/*
* We don't permit switching to a different serial port in
* midflight, although we do allow all other
* reconfiguration.
*/
s = ctrl_getset(b, "Connection/Serial", "serline",
"Select a serial line");
ctrl_editbox(s, "Serial line to connect to", 'l', 40,
HELPCTX(serial_line),
dlg_stdeditbox_handler, I(offsetof(Config,serline)),
I(sizeof(((Config *)0)->serline)));
}
s = ctrl_getset(b, "Connection/Serial", "sercfg", "Configure the serial line");
ctrl_editbox(s, "Speed (baud)", 's', 40,
HELPCTX(serial_speed),
dlg_stdeditbox_handler, I(offsetof(Config,serspeed)), I(-1));
ctrl_editbox(s, "Data bits", 'b', 40,
HELPCTX(serial_databits),
dlg_stdeditbox_handler,I(offsetof(Config,serdatabits)),I(-1));
/*
* Stop bits come in units of one half.
*/
ctrl_editbox(s, "Stop bits", 't', 40,
HELPCTX(serial_stopbits),
dlg_stdeditbox_handler,I(offsetof(Config,serstopbits)),I(-2));
ctrl_droplist(s, "Parity", 'p', 40,
HELPCTX(serial_parity),
serial_parity_handler, I(0));
ctrl_droplist(s, "Flow control", 'f', 40,
HELPCTX(serial_flow),
serial_flow_handler, I(0));
}