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 |
19 | static 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 |
55 | static 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 |
90 | void 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 |