Support for Windows PuTTY connecting straight to a local serial port
[u/mdw/putty] / sercfg.c
CommitLineData
7374c779 1/*\r
2 * sercfg.c - the serial-port specific parts of the PuTTY\r
3 * configuration box. Centralised as cross-platform code because\r
4 * more than one platform will want to use it, but not part of the\r
5 * main configuration. The expectation is that each platform's\r
6 * local config function will call out to ser_setup_config_box() if\r
7 * it needs to set up the standard serial stuff. (Of course, it can\r
8 * then apply local tweaks after ser_setup_config_box() returns, if\r
9 * it needs to.)\r
10 */\r
11\r
12#include <assert.h>\r
13#include <stdlib.h>\r
14\r
15#include "putty.h"\r
16#include "dialog.h"\r
17#include "storage.h"\r
18\r
19static void serial_parity_handler(union control *ctrl, void *dlg,\r
20 void *data, int event)\r
21{\r
22 static const struct {\r
23 const char *name;\r
24 int val;\r
25 } parities[] = {\r
26 {"None", SER_PAR_NONE},\r
27 {"Odd", SER_PAR_ODD},\r
28 {"Even", SER_PAR_EVEN},\r
29 {"Mark", SER_PAR_MARK},\r
30 {"Space", SER_PAR_SPACE},\r
31 };\r
32 int i;\r
33 Config *cfg = (Config *)data;\r
34\r
35 if (event == EVENT_REFRESH) {\r
36 dlg_update_start(ctrl, dlg);\r
37 dlg_listbox_clear(ctrl, dlg);\r
38 for (i = 0; i < lenof(parities); i++)\r
39 dlg_listbox_addwithid(ctrl, dlg, parities[i].name,\r
40 parities[i].val);\r
41 for (i = 0; i < lenof(parities); i++)\r
42 if (cfg->serparity == parities[i].val)\r
43 dlg_listbox_select(ctrl, dlg, i);\r
44 dlg_update_done(ctrl, dlg);\r
45 } else if (event == EVENT_SELCHANGE) {\r
46 int i = dlg_listbox_index(ctrl, dlg);\r
47 if (i < 0)\r
48 i = SER_PAR_NONE;\r
49 else\r
50 i = dlg_listbox_getid(ctrl, dlg, i);\r
51 cfg->serparity = i;\r
52 }\r
53}\r
54\r
55static void serial_flow_handler(union control *ctrl, void *dlg,\r
56 void *data, int event)\r
57{\r
58 static const struct {\r
59 const char *name;\r
60 int val;\r
61 } flows[] = {\r
62 {"None", SER_FLOW_NONE},\r
63 {"XON/XOFF", SER_FLOW_XONXOFF},\r
64 {"RTS/CTS", SER_FLOW_RTSCTS},\r
65 {"DSR/DTR", SER_FLOW_DSRDTR},\r
66 };\r
67 int i;\r
68 Config *cfg = (Config *)data;\r
69\r
70 if (event == EVENT_REFRESH) {\r
71 dlg_update_start(ctrl, dlg);\r
72 dlg_listbox_clear(ctrl, dlg);\r
73 for (i = 0; i < lenof(flows); i++)\r
74 dlg_listbox_addwithid(ctrl, dlg, flows[i].name,\r
75 flows[i].val);\r
76 for (i = 0; i < lenof(flows); i++)\r
77 if (cfg->serflow == flows[i].val)\r
78 dlg_listbox_select(ctrl, dlg, i);\r
79 dlg_update_done(ctrl, dlg);\r
80 } else if (event == EVENT_SELCHANGE) {\r
81 int i = dlg_listbox_index(ctrl, dlg);\r
82 if (i < 0)\r
83 i = SER_PAR_NONE;\r
84 else\r
85 i = dlg_listbox_getid(ctrl, dlg, i);\r
86 cfg->serflow = i;\r
87 }\r
88}\r
89\r
90void ser_setup_config_box(struct controlbox *b, int midsession)\r
91{\r
92 struct controlset *s;\r
93 union control *c;\r
94\r
95 /*\r
96 * Add the serial back end to the protocols list at the top of\r
97 * the config box.\r
98 */\r
99 s = ctrl_getset(b, "Session", "hostport",\r
100 "Specify your connection by host name or IP address");\r
101 {\r
102 int i;\r
103 extern void config_protocolbuttons_handler(union control *, void *,\r
104 void *, int);\r
105 for (i = 0; i < s->ncontrols; i++) {\r
106 c = s->ctrls[i];\r
107 if (c->generic.type == CTRL_RADIO &&\r
108 c->generic.handler == config_protocolbuttons_handler) {\r
109 c->radio.nbuttons++;\r
110 c->radio.ncolumns++;\r
111 c->radio.buttons =\r
112 sresize(c->radio.buttons, c->radio.nbuttons, char *);\r
113 c->radio.buttons[c->radio.nbuttons-1] =\r
114 dupstr("Serial");\r
115 c->radio.buttondata =\r
116 sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);\r
117 c->radio.buttondata[c->radio.nbuttons-1] = I(PROT_SERIAL);\r
118 if (c->radio.shortcuts) {\r
119 c->radio.shortcuts =\r
120 sresize(c->radio.shortcuts, c->radio.nbuttons, char);\r
121 c->radio.shortcuts[c->radio.nbuttons-1] = NO_SHORTCUT;\r
122 }\r
123 }\r
124 }\r
125 }\r
126\r
127 /*\r
128 * Entirely new Connection/Serial panel for serial port\r
129 * configuration.\r
130 */\r
131 ctrl_settitle(b, "Connection/Serial",\r
132 "Options controlling local serial lines");\r
133\r
134 if (!midsession) {\r
135 /*\r
136 * We don't permit switching to a different serial port in\r
137 * midflight, although we do allow all other\r
138 * reconfiguration.\r
139 */\r
140 s = ctrl_getset(b, "Connection/Serial", "serline",\r
141 "Select a serial line");\r
142 ctrl_editbox(s, "Serial line to connect to", 'l', 40,\r
143 HELPCTX(serial_line),\r
144 dlg_stdeditbox_handler, I(offsetof(Config,serline)),\r
145 I(sizeof(((Config *)0)->serline)));\r
146 }\r
147\r
148 s = ctrl_getset(b, "Connection/Serial", "sercfg", "Configure the serial line");\r
149 ctrl_editbox(s, "Speed (baud)", 's', 40,\r
150 HELPCTX(serial_speed),\r
151 dlg_stdeditbox_handler, I(offsetof(Config,serspeed)), I(-1));\r
152 ctrl_editbox(s, "Data bits", 'b', 40,\r
153 HELPCTX(serial_databits),\r
154 dlg_stdeditbox_handler,I(offsetof(Config,serdatabits)),I(-1));\r
155 /*\r
156 * Stop bits come in units of one half.\r
157 */\r
158 ctrl_editbox(s, "Stop bits", 't', 40,\r
159 HELPCTX(serial_stopbits),\r
160 dlg_stdeditbox_handler,I(offsetof(Config,serstopbits)),I(-2));\r
161 ctrl_droplist(s, "Parity", 'p', 40,\r
162 HELPCTX(serial_parity),\r
163 serial_parity_handler, I(0));\r
164 ctrl_droplist(s, "Flow control", 'f', 40,\r
165 HELPCTX(serial_flow),\r
166 serial_flow_handler, I(0));\r
167}\r