sercfg.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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. #include <assert.h>
  12. #include <stdlib.h>
  13. #include "putty.h"
  14. #include "dialog.h"
  15. #include "storage.h"
  16. static void serial_parity_handler(union control *ctrl, void *dlg,
  17. void *data, int event)
  18. {
  19. static const struct {
  20. const char *name;
  21. int val;
  22. } parities[] = {
  23. {"None", SER_PAR_NONE},
  24. {"Odd", SER_PAR_ODD},
  25. {"Even", SER_PAR_EVEN},
  26. {"Mark", SER_PAR_MARK},
  27. {"Space", SER_PAR_SPACE},
  28. };
  29. int mask = ctrl->listbox.context.i;
  30. int i, j;
  31. Conf *conf = (Conf *)data;
  32. if (event == EVENT_REFRESH) {
  33. /* Fetching this once at the start of the function ensures we
  34. * remember what the right value is supposed to be when
  35. * operations below cause reentrant calls to this function. */
  36. int oldparity = conf_get_int(conf, CONF_serparity);
  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 (mask & (1 << i)) {
  46. if (oldparity == parities[i].val) {
  47. dlg_listbox_select(ctrl, dlg, j);
  48. break;
  49. }
  50. j++;
  51. }
  52. }
  53. if (i == lenof(parities)) { /* an unsupported setting was chosen */
  54. dlg_listbox_select(ctrl, dlg, 0);
  55. oldparity = SER_PAR_NONE;
  56. }
  57. dlg_update_done(ctrl, dlg);
  58. conf_set_int(conf, CONF_serparity, oldparity); /* restore */
  59. } else if (event == EVENT_SELCHANGE) {
  60. int i = dlg_listbox_index(ctrl, dlg);
  61. if (i < 0)
  62. i = SER_PAR_NONE;
  63. else
  64. i = dlg_listbox_getid(ctrl, dlg, i);
  65. conf_set_int(conf, CONF_serparity, i);
  66. }
  67. }
  68. static void serial_flow_handler(union control *ctrl, void *dlg,
  69. void *data, int event)
  70. {
  71. static const struct {
  72. const char *name;
  73. int val;
  74. } flows[] = {
  75. {"None", SER_FLOW_NONE},
  76. {"XON/XOFF", SER_FLOW_XONXOFF},
  77. {"RTS/CTS", SER_FLOW_RTSCTS},
  78. {"DSR/DTR", SER_FLOW_DSRDTR},
  79. };
  80. int mask = ctrl->listbox.context.i;
  81. int i, j;
  82. Conf *conf = (Conf *)data;
  83. if (event == EVENT_REFRESH) {
  84. /* Fetching this once at the start of the function ensures we
  85. * remember what the right value is supposed to be when
  86. * operations below cause reentrant calls to this function. */
  87. int oldflow = conf_get_int(conf, CONF_serflow);
  88. dlg_update_start(ctrl, dlg);
  89. dlg_listbox_clear(ctrl, dlg);
  90. for (i = 0; i < lenof(flows); i++) {
  91. if (mask & (1 << i))
  92. dlg_listbox_addwithid(ctrl, dlg, flows[i].name, flows[i].val);
  93. }
  94. for (i = j = 0; i < lenof(flows); i++) {
  95. if (mask & (1 << i)) {
  96. if (oldflow == flows[i].val) {
  97. dlg_listbox_select(ctrl, dlg, j);
  98. break;
  99. }
  100. j++;
  101. }
  102. }
  103. if (i == lenof(flows)) { /* an unsupported setting was chosen */
  104. dlg_listbox_select(ctrl, dlg, 0);
  105. oldflow = SER_FLOW_NONE;
  106. }
  107. dlg_update_done(ctrl, dlg);
  108. conf_set_int(conf, CONF_serflow, oldflow);/* restore */
  109. } else if (event == EVENT_SELCHANGE) {
  110. int i = dlg_listbox_index(ctrl, dlg);
  111. if (i < 0)
  112. i = SER_FLOW_NONE;
  113. else
  114. i = dlg_listbox_getid(ctrl, dlg, i);
  115. conf_set_int(conf, CONF_serflow, i);
  116. }
  117. }
  118. void ser_setup_config_box(struct controlbox *b, int midsession,
  119. int parity_mask, int flow_mask)
  120. {
  121. struct controlset *s;
  122. union control *c;
  123. if (!midsession) {
  124. int i;
  125. extern void config_protocolbuttons_handler(union control *, void *,
  126. void *, int);
  127. /*
  128. * Add the serial back end to the protocols list at the
  129. * top of the config box.
  130. */
  131. s = ctrl_getset(b, "Session", "hostport",
  132. "Specify the destination you want to connect to");
  133. for (i = 0; i < s->ncontrols; i++) {
  134. c = s->ctrls[i];
  135. if (c->generic.type == CTRL_RADIO &&
  136. c->generic.handler == config_protocolbuttons_handler) {
  137. c->radio.nbuttons++;
  138. c->radio.ncolumns++;
  139. c->radio.buttons =
  140. sresize(c->radio.buttons, c->radio.nbuttons, char *);
  141. c->radio.buttons[c->radio.nbuttons-1] =
  142. dupstr("Serial");
  143. c->radio.buttondata =
  144. sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
  145. c->radio.buttondata[c->radio.nbuttons-1] = I(PROT_SERIAL);
  146. if (c->radio.shortcuts) {
  147. c->radio.shortcuts =
  148. sresize(c->radio.shortcuts, c->radio.nbuttons, char);
  149. c->radio.shortcuts[c->radio.nbuttons-1] = 'r';
  150. }
  151. }
  152. }
  153. }
  154. /*
  155. * Entirely new Connection/Serial panel for serial port
  156. * configuration.
  157. */
  158. ctrl_settitle(b, "Connection/Serial",
  159. "Options controlling local serial lines");
  160. if (!midsession) {
  161. /*
  162. * We don't permit switching to a different serial port in
  163. * midflight, although we do allow all other
  164. * reconfiguration.
  165. */
  166. s = ctrl_getset(b, "Connection/Serial", "serline",
  167. "Select a serial line");
  168. ctrl_editbox(s, "Serial line to connect to", 'l', 40,
  169. HELPCTX(serial_line),
  170. conf_editbox_handler, I(CONF_serline), I(1));
  171. }
  172. s = ctrl_getset(b, "Connection/Serial", "sercfg", "Configure the serial line");
  173. ctrl_editbox(s, "Speed (baud)", 's', 40,
  174. HELPCTX(serial_speed),
  175. conf_editbox_handler, I(CONF_serspeed), I(-1));
  176. ctrl_editbox(s, "Data bits", 'b', 40,
  177. HELPCTX(serial_databits),
  178. conf_editbox_handler, I(CONF_serdatabits), I(-1));
  179. /*
  180. * Stop bits come in units of one half.
  181. */
  182. ctrl_editbox(s, "Stop bits", 't', 40,
  183. HELPCTX(serial_stopbits),
  184. conf_editbox_handler, I(CONF_serstopbits), I(-2));
  185. ctrl_droplist(s, "Parity", 'p', 40,
  186. HELPCTX(serial_parity),
  187. serial_parity_handler, I(parity_mask));
  188. ctrl_droplist(s, "Flow control", 'f', 40,
  189. HELPCTX(serial_flow),
  190. serial_flow_handler, I(flow_mask));
  191. }