void freespace_setFileDescriptorCallbacks(freespace_pollfdAddedCallback addedCallback, freespace_pollfdRemovedCallback removedCallback) { userAddedCallback = addedCallback; userRemovedCallback = removedCallback; libusb_set_pollfd_notifiers(freespace_libusb_context, pollfd_added_cb, pollfd_removed_cb, NULL); }
static void exit_release_resources(int code) { if(tap_fd >= 0) { if_down(); while (wait(NULL) > 0) {} if_release(); while (wait(NULL) > 0) {} } if(ctx != NULL) { if(req_transfer != NULL) { libusb_cancel_transfer(req_transfer); libusb_free_transfer(req_transfer); } libusb_set_pollfd_notifiers(ctx, NULL, NULL, NULL); if(fds != NULL) { free(fds); } if(devh != NULL) { libusb_release_interface(devh, 0); if (kernel_driver_active) libusb_attach_kernel_driver(devh, 0); libusb_unlock_events(ctx); libusb_close(devh); } libusb_exit(ctx); } if(logfile != NULL) { fclose(logfile); } exit(code); }
void ncusb_start_descriptor_watching(struct aura_node *node, libusb_context *ctx) { /* Fetch all existing descriptors from the library */ const struct libusb_pollfd** fds_data = libusb_get_pollfds(ctx); const struct libusb_pollfd** fds = fds_data; while (*fds != NULL) { pollfd_added_cb((*fds)->fd, (*fds)->events, node); fds++; } free(fds_data); /* Register a callback */ libusb_set_pollfd_notifiers(ctx, pollfd_added_cb, pollfd_removed_cb, node); }
/** USB event source finalize() method. */ static void usb_source_finalize(GSource *source) { struct usb_source *usource; usource = (struct usb_source *)source; sr_spew("%s", __func__); libusb_set_pollfd_notifiers(usource->usb_ctx, NULL, NULL, NULL); g_ptr_array_unref(usource->pollfds); usource->pollfds = NULL; sr_session_source_destroyed(usource->session, usource->usb_ctx, source); }
/** Create an event source for libusb I/O. * * TODO: The combination of the USB I/O source with a user timeout is * conceptually broken. The user timeout supplied here is completely * unrelated to I/O -- the actual I/O timeout is set when submitting * a USB transfer. * The sigrok drivers generally use the timeout to poll device state. * Usually, this polling can be sensibly done only when there is no * active USB transfer -- i.e. it's actually mutually exclusive with * waiting for transfer completion. * Thus, the user timeout should be removed from the USB event source * API at some point. Instead, drivers should install separate timer * event sources for their polling needs. * * @param session The session the event source belongs to. * @param usb_ctx The libusb context for which to handle events. * @param timeout_ms The timeout interval in ms, or -1 to wait indefinitely. * @return A new event source object, or NULL on failure. */ static GSource *usb_source_new(struct sr_session *session, struct libusb_context *usb_ctx, int timeout_ms) { static GSourceFuncs usb_source_funcs = { .prepare = &usb_source_prepare, .check = &usb_source_check, .dispatch = &usb_source_dispatch, .finalize = &usb_source_finalize }; GSource *source; struct usb_source *usource; const struct libusb_pollfd **upollfds, **upfd; upollfds = libusb_get_pollfds(usb_ctx); if (!upollfds) { sr_err("Failed to get libusb file descriptors."); return NULL; } source = g_source_new(&usb_source_funcs, sizeof(struct usb_source)); usource = (struct usb_source *)source; g_source_set_name(source, "usb"); if (timeout_ms >= 0) { usource->timeout_us = 1000 * (int64_t)timeout_ms; usource->due_us = 0; } else { usource->timeout_us = -1; usource->due_us = INT64_MAX; } usource->session = session; usource->usb_ctx = usb_ctx; usource->pollfds = g_ptr_array_new_full(8, &usb_source_free_pollfd); for (upfd = upollfds; *upfd != NULL; upfd++) usb_pollfd_added((*upfd)->fd, (*upfd)->events, usource); #if (LIBUSB_API_VERSION >= 0x01000104) libusb_free_pollfds(upollfds); #else free(upollfds); #endif libusb_set_pollfd_notifiers(usb_ctx, &usb_pollfd_added, &usb_pollfd_removed, usource); return source; }
int start_libusb_events() { pthread_mutex_lock(&refcnt_mutex); event_loop_refcnt++; pthread_mutex_unlock(&refcnt_mutex); if(event_loop_refcnt == 1) { libusb_set_pollfd_notifiers(libusb_ctx, NULL, (libusb_pollfd_removed_cb) usb_removed, NULL); int ret = pthread_create(&event_thread, NULL, &event_loop, NULL); if(ret != 0) { ERROR_NORET("Unable to create USB events thread!"); pthread_mutex_lock(&refcnt_mutex); event_loop_refcnt=0; pthread_mutex_unlock(&refcnt_mutex); return -1; } } return 0; }
void usb_destroy_context(libusb_context *context) { const struct libusb_pollfd **pollfds = NULL; const struct libusb_pollfd **pollfd; libusb_set_pollfd_notifiers(context, NULL, NULL, NULL); pollfds = libusb_get_pollfds(context); if (pollfds == NULL) { log_error("Could not get pollfds from main libusb context"); } else { for (pollfd = pollfds; *pollfd != NULL; ++pollfd) { event_remove_source((*pollfd)->fd, EVENT_SOURCE_TYPE_USB); } #if defined(_WIN32) || (defined(LIBUSB_API_VERSION) && LIBUSB_API_VERSION >= 0x01000104) // libusb 1.0.20 libusb_free_pollfds(pollfds); // avoids possible heap-mismatch on Windows #else free(pollfds); #endif } libusb_exit(context); }
int usb_create_context(libusb_context **context) { int phase = 0; int rc; const struct libusb_pollfd **pollfds = NULL; const struct libusb_pollfd **pollfd; const struct libusb_pollfd **last_added_pollfd = NULL; rc = libusb_init(context); if (rc < 0) { log_error("Could not initialize libusb context: %s (%d)", usb_get_error_name(rc), rc); goto cleanup; } switch (log_get_effective_level()) { case LOG_LEVEL_ERROR: libusb_set_debug(*context, 1); break; case LOG_LEVEL_WARN: libusb_set_debug(*context, 2); break; case LOG_LEVEL_INFO: libusb_set_debug(*context, 3); break; case LOG_LEVEL_DEBUG: if (log_is_included(LOG_LEVEL_DEBUG, &_libusb_log_source, LOG_DEBUG_GROUP_LIBUSB)) { libusb_set_debug(*context, 4); } else { libusb_set_debug(*context, 3); } break; default: break; } phase = 1; // get pollfds from main libusb context pollfds = libusb_get_pollfds(*context); if (pollfds == NULL) { log_error("Could not get pollfds from libusb context"); goto cleanup; } for (pollfd = pollfds; *pollfd != NULL; ++pollfd) { if (event_add_source((*pollfd)->fd, EVENT_SOURCE_TYPE_USB, (*pollfd)->events, usb_handle_events, *context) < 0) { goto cleanup; } last_added_pollfd = pollfd; phase = 2; } phase = 3; // register pollfd notifiers libusb_set_pollfd_notifiers(*context, usb_add_pollfd, usb_remove_pollfd, *context); cleanup: switch (phase) { // no breaks, all cases fall through intentionally case 2: for (pollfd = pollfds; pollfd != last_added_pollfd; ++pollfd) { event_remove_source((*pollfd)->fd, EVENT_SOURCE_TYPE_USB); } case 1: libusb_exit(*context); default: break; } #if defined(_WIN32) || (defined(LIBUSB_API_VERSION) && LIBUSB_API_VERSION >= 0x01000104) // libusb 1.0.20 libusb_free_pollfds(pollfds); // avoids possible heap-mismatch on Windows #else free(pollfds); #endif return phase == 3 ? 0 : -1; }
int main(int argc, char **argv) { struct sigaction sigact; struct sigevent sev; struct itimerspec its; int r = 1; parse_args(argc, argv); sigact.sa_handler = sighandler_exit; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(SIGINT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); sigaction(SIGQUIT, &sigact, NULL); sigact.sa_handler = sighandler_wait_child; sigaction(SIGCHLD, &sigact, NULL); sigact.sa_handler = sighandler_stats; sigfillset(&sigact.sa_mask); if (stats_period == 0) sigaction(SIGUSR1, &sigact, NULL); if (logfile != NULL) { set_wmlogger(argv[0], WMLOGGER_FILE, logfile); } else if (daemonize) { set_wmlogger(argv[0], WMLOGGER_SYSLOG, NULL); } else { set_wmlogger(argv[0], WMLOGGER_FILE, stderr); } if (daemonize) { daemon(0, 0); } if (stats_period != 0) { sigemptyset(&sigact.sa_mask); sigaction(SIGRTMIN, &sigact, NULL); // create the POSIX timer sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGRTMIN; sev.sigev_value.sival_ptr = (void *) &timerid; if (timer_create(CLOCK_MONOTONIC, &sev, &timerid) == 0) { // start the POSIX timer its.it_value.tv_sec = stats_period; its.it_value.tv_nsec = 0; its.it_interval.tv_sec = its.it_value.tv_sec; its.it_interval.tv_nsec = its.it_value.tv_nsec; timer_settime(timerid, 0, &its, NULL); } } r = libusb_init(&ctx); if (r < 0) { wmlog_msg(0, "failed to initialise libusb"); exit_release_resources(1); } if (pid_fname && !write_pidfile(pid_fname)) { wmlog_msg(0, "failed to create pid file %s", pid_fname); exit_release_resources(1); } devh = find_wimax_device(); if (devh == NULL) { wmlog_msg(0, "Could not find/open device"); exit_release_resources(1); } wmlog_msg(0, "Device found"); if (detach_dvd && libusb_kernel_driver_active(devh, IF_DVD) == 1) { r = libusb_detach_kernel_driver(devh, IF_DVD); if (r < 0) { wmlog_msg(0, "kernel driver detach error %d", r); } else { wmlog_msg(0, "detached pseudo-DVD kernel driver"); } } if (libusb_kernel_driver_active(devh, IF_MODEM) == 1) { kernel_driver_active = 1; r = libusb_detach_kernel_driver(devh, IF_MODEM); if (r < 0) { wmlog_msg(0, "kernel driver detach error %d", r); } else { wmlog_msg(0, "detached modem kernel driver"); } } r = libusb_claim_interface(devh, IF_MODEM); if (r < 0) { wmlog_msg(0, "Claim usb interface error %d", r); exit_release_resources(1); } wmlog_msg(0, "Claimed interface"); alloc_fds(); libusb_set_pollfd_notifiers(ctx, cb_add_pollfd, cb_remove_pollfd, NULL); r = init(); if (r < 0) { wmlog_msg(0, "init error %d", r); exit_release_resources(1); } if_create(); cb_add_pollfd(tap_fd, POLLIN, NULL); r = scan_loop(); if (r < 0) { wmlog_msg(0, "scan_loop error %d", r); exit_release_resources(1); } exit_release_resources(0); return 0; }
int main(int argc, char **argv) { struct sigaction sigact; int r = 1; parse_args(argc, argv); sigact.sa_handler = sighandler_exit; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(SIGINT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); sigaction(SIGQUIT, &sigact, NULL); sigact.sa_handler = sighandler_wait_child; sigaction(SIGCHLD, &sigact, NULL); if (logfile != NULL) { set_wmlogger(argv[0], WMLOGGER_FILE, logfile); } else if (daemonize) { set_wmlogger(argv[0], WMLOGGER_SYSLOG, NULL); } else { set_wmlogger(argv[0], WMLOGGER_FILE, stderr); } if (daemonize) { daemon(0, 0); } r = libusb_init(&ctx); if (r < 0) { wmlog_msg(0, "failed to initialise libusb"); exit_release_resources(1); } devh = find_wimax_device(); if (devh == NULL) { wmlog_msg(0, "Could not find/open device"); exit_release_resources(1); } wmlog_msg(0, "Device found"); if (detach_dvd && libusb_kernel_driver_active(devh, IF_DVD) == 1) { r = libusb_detach_kernel_driver(devh, IF_DVD); if (r < 0) { wmlog_msg(0, "kernel driver detach error %d", r); } else { wmlog_msg(0, "detached pseudo-DVD kernel driver"); } } if (libusb_kernel_driver_active(devh, IF_MODEM) == 1) { kernel_driver_active = 1; r = libusb_detach_kernel_driver(devh, IF_MODEM); if (r < 0) { wmlog_msg(0, "kernel driver detach error %d", r); } else { wmlog_msg(0, "detached modem kernel driver"); } } r = libusb_claim_interface(devh, IF_MODEM); if (r < 0) { wmlog_msg(0, "Claim usb interface error %d", r); exit_release_resources(1); } wmlog_msg(0, "Claimed interface"); alloc_fds(); libusb_set_pollfd_notifiers(ctx, cb_add_pollfd, cb_remove_pollfd, NULL); r = init(); if (r < 0) { wmlog_msg(0, "init error %d", r); exit_release_resources(1); } if_create(); cb_add_pollfd(tap_fd, POLLIN, NULL); r = scan_loop(); if (r < 0) { wmlog_msg(0, "scan_loop error %d", r); exit_release_resources(1); } exit_release_resources(0); return 0; }