#include "libsigrok.h"
#include "libsigrok-internal.h"
-/* Message logging helpers with subsystem-specific prefix string. */
-#define LOG_PREFIX "serial: "
-#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
-#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
-#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
-#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
-#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
-#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
+#define LOG_PREFIX "serial"
/**
* Open the specified serial port.
return SR_ERR_ARG;
case SP_ERR_FAIL:
error = sp_last_error_message();
- sr_err("Error opening port: %s.", error);
+ sr_err("Error opening port (%d): %s.",
+ sp_last_error_code(), error);
sp_free_error_message(error);
return SR_ERR;
}
return SR_ERR_ARG;
case SP_ERR_FAIL:
error = sp_last_error_message();
- sr_err("Error closing port: %s.", error);
+ sr_err("Error closing port (%d): %s.",
+ sp_last_error_code(), error);
sp_free_error_message(error);
return SR_ERR;
}
return SR_ERR_ARG;
case SP_ERR_FAIL:
error = sp_last_error_message();
- sr_err("Error flushing port: %s.", error);
+ sr_err("Error flushing port (%d): %s.",
+ sp_last_error_code(), error);
sp_free_error_message(error);
return SR_ERR;
}
return SR_OK;
}
-/**
- * Write a number of bytes to the specified serial port.
- *
- * @param serial Previously initialized serial port structure.
- * @param buf Buffer containing the bytes to write.
- * @param count Number of bytes to write.
- *
- * @return The number of bytes written, or a negative error code upon failure.
- */
-SR_PRIV int serial_write(struct sr_serial_dev_inst *serial,
- const void *buf, size_t count)
+static int _serial_write(struct sr_serial_dev_inst *serial,
+ const void *buf, size_t count, int nonblocking)
{
ssize_t ret;
char *error;
return SR_ERR;
}
- if (serial->nonblocking)
+ if (nonblocking)
ret = sp_nonblocking_write(serial->data, buf, count);
else
ret = sp_blocking_write(serial->data, buf, count, 0);
return SR_ERR_ARG;
case SP_ERR_FAIL:
error = sp_last_error_message();
- sr_err("Write error: %s.", error);
+ sr_err("Write error (%d): %s.", sp_last_error_code(), error);
sp_free_error_message(error);
return SR_ERR;
}
}
/**
- * Read a number of bytes from the specified serial port.
+ * Write a number of bytes to the specified serial port.
*
* @param serial Previously initialized serial port structure.
- * @param buf Buffer where to store the bytes that are read.
- * @param count The number of bytes to read.
+ * @param buf Buffer containing the bytes to write.
+ * @param count Number of bytes to write.
*
- * @return The number of bytes read, or a negative error code upon failure.
+ * @return The number of bytes written, or a negative error code upon failure.
*/
-SR_PRIV int serial_read(struct sr_serial_dev_inst *serial, void *buf,
- size_t count)
+SR_PRIV int serial_write(struct sr_serial_dev_inst *serial,
+ const void *buf, size_t count)
+{
+ return _serial_write(serial, buf, count, serial->nonblocking);
+}
+
+SR_PRIV int serial_write_blocking(struct sr_serial_dev_inst *serial,
+ const void *buf, size_t count)
+{
+ return _serial_write(serial, buf, count, 0);
+}
+
+SR_PRIV int serial_write_nonblocking(struct sr_serial_dev_inst *serial,
+ const void *buf, size_t count)
+{
+ return _serial_write(serial, buf, count, 1);
+}
+
+static int _serial_read(struct sr_serial_dev_inst *serial, void *buf,
+ size_t count, int nonblocking)
{
ssize_t ret;
char *error;
return SR_ERR;
}
- if (serial->nonblocking)
+ if (nonblocking)
ret = sp_nonblocking_read(serial->data, buf, count);
else
ret = sp_blocking_read(serial->data, buf, count, 0);
return SR_ERR_ARG;
case SP_ERR_FAIL:
error = sp_last_error_message();
- sr_err("Read error: %s.", error);
+ sr_err("Read error (%d): %s.", sp_last_error_code(), error);
sp_free_error_message(error);
return SR_ERR;
}
return ret;
}
+/**
+ * Read a number of bytes from the specified serial port.
+ *
+ * @param serial Previously initialized serial port structure.
+ * @param buf Buffer where to store the bytes that are read.
+ * @param count The number of bytes to read.
+ *
+ * @return The number of bytes read, or a negative error code upon failure.
+ */
+SR_PRIV int serial_read(struct sr_serial_dev_inst *serial, void *buf,
+ size_t count)
+{
+ return _serial_read(serial, buf, count, serial->nonblocking);
+}
+
+SR_PRIV int serial_read_blocking(struct sr_serial_dev_inst *serial, void *buf,
+ size_t count)
+{
+ return _serial_read(serial, buf, count, 0);
+}
+
+SR_PRIV int serial_read_nonblocking(struct sr_serial_dev_inst *serial, void *buf,
+ size_t count)
+{
+ return _serial_read(serial, buf, count, 1);
+}
+
/**
* Set serial parameters for the specified serial port.
*
return SR_ERR_ARG;
case SP_ERR_FAIL:
error = sp_last_error_message();
- sr_err("Error setting serial port parameters: %s.", error);
+ sr_err("Error setting serial port parameters (%d): %s.",
+ sp_last_error_code(), error);
sp_free_error_message(error);
return SR_ERR;
}
return SR_OK;
}
-SR_PRIV int serial_source_add(struct sr_serial_dev_inst *serial, int events,
- int timeout, sr_receive_data_callback_t cb, void *cb_data)
-{
#ifdef _WIN32
- return SR_ERR;
+typedef HANDLE event_handle;
#else
- int fd;
- sp_get_port_handle(serial->data, &fd);
- return sr_source_add(fd, events, timeout, cb, cb_data);
+typedef int event_handle;
#endif
+
+SR_PRIV int serial_source_add(struct sr_serial_dev_inst *serial, int events,
+ int timeout, sr_receive_data_callback_t cb, void *cb_data)
+{
+ enum sp_event mask = 0;
+ unsigned int i;
+
+ if (sp_new_event_set(&serial->event_set) != SP_OK)
+ return SR_ERR;
+
+ if (events & G_IO_IN)
+ mask |= SP_EVENT_RX_READY;
+ if (events & G_IO_OUT)
+ mask |= SP_EVENT_TX_READY;
+ if (events & G_IO_ERR)
+ mask |= SP_EVENT_ERROR;
+
+ if (sp_add_port_events(serial->event_set, serial->data, mask) != SP_OK) {
+ sp_free_event_set(serial->event_set);
+ return SR_ERR;
+ }
+
+ serial->pollfds = (GPollFD *) g_malloc0(sizeof(GPollFD) * serial->event_set->count);
+
+ for (i = 0; i < serial->event_set->count; i++) {
+
+ serial->pollfds[i].fd = ((event_handle *) serial->event_set->handles)[i];
+
+ mask = serial->event_set->masks[i];
+
+ if (mask & SP_EVENT_RX_READY)
+ serial->pollfds[i].events |= G_IO_IN;
+ if (mask & SP_EVENT_TX_READY)
+ serial->pollfds[i].events |= G_IO_OUT;
+ if (mask & SP_EVENT_ERROR)
+ serial->pollfds[i].events |= G_IO_ERR;
+
+ if (sr_session_source_add_pollfd(&serial->pollfds[i],
+ timeout, cb, cb_data) != SR_OK)
+ return SR_ERR;
+ }
+
+ return SR_OK;
}
SR_PRIV int serial_source_remove(struct sr_serial_dev_inst *serial)
{
-#ifdef _WIN32
- return SR_ERR;
-#else
- int fd;
- sp_get_port_handle(serial->data, &fd);
- return sr_source_remove(fd);
-#endif
+ unsigned int i;
+
+ for (i = 0; i < serial->event_set->count; i++)
+ if (sr_session_source_remove_pollfd(&serial->pollfds[i]) != SR_OK)
+ return SR_ERR;
+
+ g_free(serial->pollfds);
+ sp_free_event_set(serial->event_set);
+
+ serial->pollfds = NULL;
+ serial->event_set = NULL;
+
+ return SR_OK;
}