X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=serialport.c;h=3a89609af2585338b8438c3b0e5f026adc5e0998;hb=a6cda1e8c71f08eee9bdeb862e26d7d4b943e997;hp=5ad216cc3b43e3ea415b6e5f89c2fb98e0218670;hpb=ea667be751d42100f5927b4ab49a02c9d207250d;p=libserialport.git diff --git a/serialport.c b/serialport.c index 5ad216c..3a89609 100644 --- a/serialport.c +++ b/serialport.c @@ -108,8 +108,6 @@ void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler; #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates) -#define TRY(x) do { int ret = x; if (ret != SP_OK) return ret; } while (0) - /* Debug output macros. */ #define DEBUG(fmt, ...) do { if (sp_debug_handler) sp_debug_handler(fmt ".\n", ##__VA_ARGS__); } while (0) #define DEBUG_ERROR(err, msg) DEBUG("%s returning " #err ": " msg, __func__) @@ -137,6 +135,8 @@ void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler; #define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = err; } while (0) #define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__) +#define TRY(x) do { int ret = x; if (ret != SP_OK) RETURN_CODEVAL(ret); } while (0) + /* Helper functions. */ static struct sp_port **list_append(struct sp_port **list, const char *portname); static enum sp_return get_config(struct sp_port *port, struct port_data *data, @@ -246,10 +246,13 @@ fail: enum sp_return sp_list_ports(struct sp_port ***list_ptr) { struct sp_port **list; - int ret = SP_OK; + int ret = SP_ERR_SUPP; TRACE("%p", list_ptr); + if (!list_ptr) + RETURN_ERROR(SP_ERR_ARG, "Null result pointer"); + DEBUG("Enumerating ports"); if (!(list = malloc(sizeof(struct sp_port **)))) @@ -266,6 +269,8 @@ enum sp_return sp_list_ports(struct sp_port ***list_ptr) char *name; int name_len; + ret = SP_OK; + DEBUG("Opening registry key"); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) { @@ -336,6 +341,8 @@ out_done: CFTypeRef cf_path; Boolean result; + ret = SP_OK; + DEBUG("Getting IOKit master port"); if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) { SET_FAIL(ret, "IOMasterPort() failed"); @@ -399,6 +406,8 @@ out_done: int fd, ioctl_result; struct serial_struct serial_info; + ret = SP_OK; + DEBUG("Enumerating tty devices"); ud = udev_new(); ud_enumerate = udev_enumerate_new(ud); @@ -453,10 +462,13 @@ out: udev_unref(ud); #endif - if (ret == SP_OK) { + switch (ret) { + case SP_OK: *list_ptr = list; RETURN_OK(); - } else { + case SP_ERR_SUPP: + DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform."); + default: if (list) sp_free_port_list(list); *list_ptr = NULL; @@ -470,6 +482,11 @@ void sp_free_port_list(struct sp_port **list) TRACE("%p", list); + if (!list) { + DEBUG("Null list"); + RETURN(); + } + DEBUG("Freeing port list"); for (i = 0; list[i]; i++) @@ -479,28 +496,36 @@ void sp_free_port_list(struct sp_port **list) RETURN(); } -#ifdef _WIN32 #define CHECK_PORT() do { \ if (port == NULL) \ RETURN_ERROR(SP_ERR_ARG, "Null port"); \ + if (port->name == NULL) \ + RETURN_ERROR(SP_ERR_ARG, "Null port name"); \ +} while (0) +#ifdef _WIN32 +#define CHECK_PORT_HANDLE() do { \ if (port->hdl == INVALID_HANDLE_VALUE) \ RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \ -} while(0); +} while (0) #else -#define CHECK_PORT() do { \ - if (port == NULL) \ - RETURN_ERROR(SP_ERR_ARG, "Null port"); \ +#define CHECK_PORT_HANDLE() do { \ if (port->fd < 0) \ RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \ -} while(0); +} while (0) #endif +#define CHECK_OPEN_PORT() do { \ + CHECK_PORT(); \ + CHECK_PORT_HANDLE(); \ +} while (0) enum sp_return sp_open(struct sp_port *port, enum sp_mode flags) { TRACE("%p, %x", port, flags); - if (!port) - RETURN_ERROR(SP_ERR_ARG, "Null port"); + CHECK_PORT(); + + if (flags > (SP_MODE_READ | SP_MODE_WRITE | SP_MODE_NONBLOCK)) + RETURN_ERROR(SP_ERR_ARG, "Invalid flags"); DEBUG("Opening port %s", port->name); @@ -582,7 +607,7 @@ enum sp_return sp_close(struct sp_port *port) { TRACE("%p", port); - CHECK_PORT(); + CHECK_OPEN_PORT(); DEBUG("Closing port %s", port->name); @@ -605,7 +630,10 @@ enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers) { TRACE("%p, %x", port, buffers); - CHECK_PORT(); + CHECK_OPEN_PORT(); + + if (buffers > SP_BUF_BOTH) + RETURN_ERROR(SP_ERR_ARG, "Invalid buffer selection"); const char *buffer_names[] = {"input", "output", "both"}; @@ -641,7 +669,7 @@ enum sp_return sp_drain(struct sp_port *port) { TRACE("%p", port); - CHECK_PORT(); + CHECK_OPEN_PORT(); DEBUG("Draining port %s", port->name); @@ -662,7 +690,7 @@ enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count) { TRACE("%p, %p, %d", port, buf, count); - CHECK_PORT(); + CHECK_OPEN_PORT(); if (!buf) RETURN_ERROR(SP_ERR_ARG, "Null buffer"); @@ -691,7 +719,7 @@ enum sp_return sp_read(struct sp_port *port, void *buf, size_t count) { TRACE("%p, %p, %d", port, buf, count); - CHECK_PORT(); + CHECK_OPEN_PORT(); if (!buf) RETURN_ERROR(SP_ERR_ARG, "Null buffer"); @@ -1394,7 +1422,7 @@ enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config * TRACE("%p, %p", port, config); - CHECK_PORT(); + CHECK_OPEN_PORT(); if (!config) RETURN_ERROR(SP_ERR_ARG, "Null config"); @@ -1409,7 +1437,7 @@ enum sp_return sp_set_config(struct sp_port *port, const struct sp_port_config * struct port_data data; \ struct sp_port_config config; \ TRACE("%p, %d", port, x); \ - CHECK_PORT(); \ + CHECK_OPEN_PORT(); \ TRY(get_config(port, &data, &config)); \ config.x = x; \ TRY(set_config(port, &data, &config)); \ @@ -1433,7 +1461,10 @@ enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontrol flow TRACE("%p, %d", port, flowcontrol); - CHECK_PORT(); + CHECK_OPEN_PORT(); + + if (flowcontrol > SP_FLOWCONTROL_DTRDSR) + RETURN_ERROR(SP_ERR_ARG, "Invalid flow control setting"); TRY(get_config(port, &data, &config)); @@ -1469,7 +1500,7 @@ enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals) { TRACE("%p, %p", port, signals); - CHECK_PORT(); + CHECK_OPEN_PORT(); if (!signals) RETURN_ERROR(SP_ERR_ARG, "Null result pointer"); @@ -1485,9 +1516,9 @@ enum sp_return sp_get_signals(struct sp_port *port, enum sp_signal *signals) *signals |= SP_SIG_CTS; if (bits & MS_DSR_ON) *signals |= SP_SIG_DSR; - if (bits & MS_RING_ON) - *signals |= SP_SIG_DCD; if (bits & MS_RLSD_ON) + *signals |= SP_SIG_DCD; + if (bits & MS_RING_ON) *signals |= SP_SIG_RI; #else int bits; @@ -1509,7 +1540,7 @@ enum sp_return sp_start_break(struct sp_port *port) { TRACE("%p", port); - CHECK_PORT(); + CHECK_OPEN_PORT(); #ifdef _WIN32 if (SetCommBreak(port->hdl) == 0) RETURN_FAIL("SetCommBreak() failed"); @@ -1525,7 +1556,7 @@ enum sp_return sp_end_break(struct sp_port *port) { TRACE("%p", port); - CHECK_PORT(); + CHECK_OPEN_PORT(); #ifdef _WIN32 if (ClearCommBreak(port->hdl) == 0) RETURN_FAIL("ClearCommBreak() failed");