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