int obsd_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds, int num_ready) { struct libusb_device_handle *handle; struct handle_priv *hpriv = NULL; struct usbi_transfer *itransfer; struct pollfd *pollfd; int i, err = 0; usbi_dbg(""); pthread_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { pollfd = &fds[i]; if (!pollfd->revents) continue; hpriv = NULL; num_ready--; list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) { hpriv = (struct handle_priv *)handle->os_priv; if (hpriv->pipe[0] == pollfd->fd) break; hpriv = NULL; } if (NULL == hpriv) { usbi_dbg("fd %d is not an event pipe!", pollfd->fd); err = ENOENT; break; } if (pollfd->revents & POLLERR) { usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]); usbi_handle_disconnect(handle); continue; } if (read(hpriv->pipe[0], &itransfer, sizeof(itransfer)) < 0) { err = errno; break; } if ((err = usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED))) break; } pthread_mutex_unlock(&ctx->open_devs_lock); if (err) return _errno_to_libusb(err); return (LIBUSB_SUCCESS); }
static int wince_handle_events( struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) { struct wince_transfer_priv* transfer_priv = NULL; POLL_NFDS_TYPE i = 0; BOOL found = FALSE; struct usbi_transfer *transfer; DWORD io_size, io_result; int r = LIBUSB_SUCCESS; usbi_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); if (!fds[i].revents) continue; num_ready--; // Because a Windows OVERLAPPED is used for poll emulation, // a pollable fd is created and stored with each transfer usbi_mutex_lock(&ctx->flying_transfers_lock); list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { transfer_priv = usbi_transfer_get_os_priv(transfer); if (transfer_priv->pollable_fd.fd == fds[i].fd) { found = TRUE; break; } } usbi_mutex_unlock(&ctx->flying_transfers_lock); if (found && HasOverlappedIoCompleted(transfer_priv->pollable_fd.overlapped)) { io_result = (DWORD)transfer_priv->pollable_fd.overlapped->Internal; io_size = (DWORD)transfer_priv->pollable_fd.overlapped->InternalHigh; usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd); // let handle_callback free the event using the transfer wfd // If you don't use the transfer wfd, you run a risk of trying to free a // newly allocated wfd that took the place of the one from the transfer. wince_handle_callback(transfer, io_result, io_size); } else if (found) { usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]); r = LIBUSB_ERROR_OTHER; break; } else { usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]); r = LIBUSB_ERROR_NOT_FOUND; break; } } usbi_mutex_unlock(&ctx->open_devs_lock); return r; }
static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) { struct windows_context_priv *priv = _context_priv(ctx); struct usbi_transfer *itransfer; DWORD io_size, io_result; POLL_NFDS_TYPE i; bool found; int transfer_fd; int r = LIBUSB_SUCCESS; usbi_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); if (!fds[i].revents) continue; num_ready--; // Because a Windows OVERLAPPED is used for poll emulation, // a pollable fd is created and stored with each transfer found = false; transfer_fd = -1; usbi_mutex_lock(&ctx->flying_transfers_lock); list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) { transfer_fd = priv->backend->get_transfer_fd(itransfer); if (transfer_fd == fds[i].fd) { found = true; break; } } usbi_mutex_unlock(&ctx->flying_transfers_lock); if (found) { priv->backend->get_overlapped_result(itransfer, &io_result, &io_size); usbi_remove_pollfd(ctx, transfer_fd); // let handle_callback free the event using the transfer wfd // If you don't use the transfer wfd, you run a risk of trying to free a // newly allocated wfd that took the place of the one from the transfer. windows_handle_callback(priv->backend, itransfer, io_result, io_size); } else { usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i].fd); r = LIBUSB_ERROR_NOT_FOUND; break; } } usbi_mutex_unlock(&ctx->open_devs_lock); return r; }
void obsd_close(struct libusb_device_handle *handle) { struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; usbi_dbg("close: fd %d", dpriv->fd); close(dpriv->fd); dpriv->fd = -1; usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]); close(hpriv->pipe[0]); close(hpriv->pipe[1]); }