+#define TRY(x) do { int ret = x; if (ret != SP_OK) return ret; } while (0)
+
+enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config *config)
+{
+ struct port_data data;
+ struct sp_port_config prev_config;
+
+ CHECK_PORT();
+
+ if (!config)
+ return SP_ERR_ARG;
+
+ TRY(get_config(port, &data, &prev_config));
+ TRY(set_config(port, &data, config));
+
+ return SP_OK;
+}
+
+#define CREATE_SETTER(x, type) int sp_set_##x(struct sp_port *port, type x) { \
+ struct port_data data; \
+ struct sp_port_config config; \
+ CHECK_PORT(); \
+ TRY(get_config(port, &data, &config)); \
+ config.x = x; \
+ TRY(set_config(port, &data, &config)); \
+ return SP_OK; \
+}
+
+CREATE_SETTER(baudrate, int)
+CREATE_SETTER(bits, int)
+CREATE_SETTER(parity, enum sp_parity)
+CREATE_SETTER(stopbits, int)
+CREATE_SETTER(rts, enum sp_rts)
+CREATE_SETTER(cts, enum sp_cts)
+CREATE_SETTER(dtr, enum sp_dtr)
+CREATE_SETTER(dsr, enum sp_dsr)
+CREATE_SETTER(xon_xoff, enum sp_xonxoff)
+
+enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flowcontrol)
+{
+ struct port_data data;
+ struct sp_port_config config;
+
+ CHECK_PORT();
+
+ TRY(get_config(port, &data, &config));
+
+ if (flowcontrol == SP_FLOWCONTROL_XONXOFF)
+ config.xon_xoff = SP_XONXOFF_INOUT;
+ else
+ config.xon_xoff = SP_XONXOFF_DISABLED;
+
+ if (flowcontrol == SP_FLOWCONTROL_RTSCTS) {
+ config.rts = SP_RTS_FLOW_CONTROL;
+ config.cts = SP_CTS_FLOW_CONTROL;
+ } else {
+ if (config.rts == SP_RTS_FLOW_CONTROL)
+ config.rts = SP_RTS_ON;
+ config.cts = SP_CTS_IGNORE;
+ }
+
+ if (flowcontrol == SP_FLOWCONTROL_DTRDSR) {
+ config.dtr = SP_DTR_FLOW_CONTROL;
+ config.dsr = SP_DSR_FLOW_CONTROL;
+ } else {
+ if (config.dtr == SP_DTR_FLOW_CONTROL)
+ config.dtr = SP_DTR_ON;
+ config.dsr = SP_DSR_IGNORE;
+ }
+
+ TRY(set_config(port, &data, &config));
+
+ return SP_OK;
+}
+