/** @private */ SR_PRIV int serial_source_add(struct sr_session *session, struct sr_serial_dev_inst *serial, int events, int timeout, sr_receive_data_callback cb, void *cb_data) { struct sp_event_set *event_set; gintptr poll_fd; unsigned int poll_events; enum sp_event mask = 0; if ((events & (G_IO_IN|G_IO_ERR)) && (events & G_IO_OUT)) { sr_err("Cannot poll input/error and output simultaneously."); return SR_ERR_ARG; } if (sp_new_event_set(&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(event_set, serial->data, mask) != SP_OK) { sp_free_event_set(event_set); return SR_ERR; } if (event_set->count != 1) { sr_err("Unexpected number (%u) of event handles to poll.", event_set->count); sp_free_event_set(event_set); return SR_ERR; } poll_fd = (gintptr) ((event_handle *)event_set->handles)[0]; mask = event_set->masks[0]; sp_free_event_set(event_set); poll_events = 0; if (mask & SP_EVENT_RX_READY) poll_events |= G_IO_IN; if (mask & SP_EVENT_TX_READY) poll_events |= G_IO_OUT; if (mask & SP_EVENT_ERROR) poll_events |= G_IO_ERR; /* * Using serial->data as the key for the event source is not quite * proper, as it makes it impossible to create another event source * for the same serial port. However, these fixed keys will soon be * removed from the API anyway, so this is OK for now. */ return sr_session_fd_source_add(session, serial->data, poll_fd, poll_events, timeout, cb, cb_data); }
/** * Add an event source for a file descriptor. * * @param session The session to use. Must not be NULL. * @param fd The file descriptor, or a negative value to create a timer source. * @param events Events to check for. * @param timeout Max time in ms to wait before the callback is called, * or -1 to wait indefinitely. * @param cb Callback function to add. Must not be NULL. * @param cb_data Data for the callback function. Can be NULL. * * @retval SR_OK Success. * @retval SR_ERR_ARG Invalid argument. * * @since 0.3.0 * @private */ SR_PRIV int sr_session_source_add(struct sr_session *session, int fd, int events, int timeout, sr_receive_data_callback cb, void *cb_data) { if (fd < 0 && timeout < 0) { sr_err("Cannot create timer source without timeout."); return SR_ERR_ARG; } return sr_session_fd_source_add(session, GINT_TO_POINTER(fd), fd, events, timeout, cb, cb_data); }
/** * Add an event source for a GPollFD. * * @param session The session to use. Must not be NULL. * @param pollfd The GPollFD. Must not be NULL. * @param timeout Max time in ms to wait before the callback is called, * or -1 to wait indefinitely. * @param cb Callback function to add. Must not be NULL. * @param cb_data Data for the callback function. Can be NULL. * * @retval SR_OK Success. * @retval SR_ERR_ARG Invalid argument. * * @since 0.3.0 * @private */ SR_PRIV int sr_session_source_add_pollfd(struct sr_session *session, GPollFD *pollfd, int timeout, sr_receive_data_callback cb, void *cb_data) { if (!pollfd) { sr_err("%s: pollfd was NULL", __func__); return SR_ERR_ARG; } return sr_session_fd_source_add(session, pollfd, pollfd->fd, pollfd->events, timeout, cb, cb_data); }
/** * Add an event source for a GIOChannel. * * @param session The session to use. Must not be NULL. * @param channel The GIOChannel. * @param events Events to poll on. * @param timeout Max time in ms to wait before the callback is called, * or -1 to wait indefinitely. * @param cb Callback function to add. Must not be NULL. * @param cb_data Data for the callback function. Can be NULL. * * @retval SR_OK Success. * @retval SR_ERR_ARG Invalid argument. * * @since 0.3.0 * @private */ SR_PRIV int sr_session_source_add_channel(struct sr_session *session, GIOChannel *channel, int events, int timeout, sr_receive_data_callback cb, void *cb_data) { GPollFD pollfd; if (!channel) { sr_err("%s: channel was NULL", __func__); return SR_ERR_ARG; } /* We should be using g_io_create_watch(), but can't without * changing the driver API, as the callback signature is different. */ #ifdef G_OS_WIN32 g_io_channel_win32_make_pollfd(channel, events, &pollfd); #else pollfd.fd = g_io_channel_unix_get_fd(channel); pollfd.events = events; #endif return sr_session_fd_source_add(session, channel, pollfd.fd, pollfd.events, timeout, cb, cb_data); }