void next_event(struct params *p) { struct timeval to, now; int el; int max; fd_set fds; int rtr = 3*1000; /* figure out select timeout */ if (gettimeofday(&now, NULL) == -1) err(1, "gettimeofday()"); /* check beacon timeout */ el = elapsed(&p->blast, &now); if (el >= p->bint) { send_beacon(p); el = 0; } el = p->bint - el; to.tv_sec = el/1000/1000; to.tv_usec = el - to.tv_sec*1000*1000; /* check tx timeout */ if (p->packet_try) { el = elapsed(&p->plast, &now); if (el >= rtr) { /* check if we gotta retransmit more */ if (retransmit(p)) { el = 0; } else el = -1; } /* gotta retransmit in future */ if (el != -1) { el = rtr - el; if ((to.tv_sec*1000*1000 + to.tv_usec) > el) { to.tv_sec = el/1000/1000; to.tv_usec = el - to.tv_sec*1000*1000; } } } /* select */ FD_ZERO(&fds); FD_SET(p->rx, &fds); FD_SET(p->tap, &fds); max = p->rx > p->tap ? p->rx : p->tap; if (select(max+1, &fds, NULL, NULL, &to) == -1) err(1, "select()"); if (FD_ISSET(p->tap, &fds)) read_tap(p); if (FD_ISSET(p->rx, &fds)) read_wifi(p); }
static int process_events_once(int timeout) { struct timeval tv = {0, 0}; int r; int libusb_delay; int delay; unsigned int i; char process_libusb = 0; r = libusb_get_next_timeout(ctx, &tv); if (r == 1 && tv.tv_sec == 0 && tv.tv_usec == 0) { r = libusb_handle_events_timeout(ctx, &tv); } delay = libusb_delay = tv.tv_sec * 1000 + tv.tv_usec; if (delay <= 0 || delay > timeout) { delay = timeout; } CHECK_NEGATIVE(poll(fds, nfds, delay)); process_libusb = (r == 0 && delay == libusb_delay); for (i = 0; i < nfds; ++i) { if (fds[i].fd == tap_fd) { if (fds[i].revents) { CHECK_NEGATIVE(read_tap()); } continue; } process_libusb |= fds[i].revents; } if (process_libusb) { struct timeval tv = {.tv_sec = 0, .tv_usec = 0}; CHECK_NEGATIVE(libusb_handle_events_timeout(ctx, &tv)); } return 0; } /* handle events until timeout is reached or all of the events in event_mask happen */ static int process_events_by_mask(int timeout, unsigned int event_mask) { struct timeval start, curr; int r; int delay = timeout; CHECK_NEGATIVE(gettimeofday(&start, NULL)); wd_status.info_updated &= ~event_mask; while ((event_mask == 0 || (wd_status.info_updated & event_mask) != event_mask) && delay >= 0) { long a; CHECK_NEGATIVE(process_events_once(delay)); if (device_disconnected) { exit_release_resources(0); } CHECK_NEGATIVE(gettimeofday(&curr, NULL)); a = (curr.tv_sec - start.tv_sec) * 1000 + (curr.tv_usec - start.tv_usec) / 1000; delay = timeout - a; } wd_status.info_updated &= ~event_mask; return (delay > 0) ? delay : 0; } int alloc_fds() { int i; const struct libusb_pollfd **usb_fds = libusb_get_pollfds(ctx); if (!usb_fds) { return -1; } nfds = 0; while (usb_fds[nfds]) { nfds++; } if (tap_fd != -1) { nfds++; } if(fds != NULL) { free(fds); } fds = (struct pollfd*)calloc(nfds, sizeof(struct pollfd)); for (i = 0; usb_fds[i]; ++i) { fds[i].fd = usb_fds[i]->fd; fds[i].events = usb_fds[i]->events; set_coe(usb_fds[i]->fd); } if (tap_fd != -1) { fds[i].fd = tap_fd; fds[i].events = POLLIN; fds[i].revents = 0; } free(usb_fds); return 0; }