diff --git a/lib/libusb/libusb10_hotplug.c b/lib/libusb/libusb10_hotplug.c --- a/lib/libusb/libusb10_hotplug.c +++ b/lib/libusb/libusb10_hotplug.c @@ -40,6 +40,10 @@ #include #include #include +#include +#include +#include +#include #endif #define libusb_device_handle libusb20_device @@ -79,6 +83,8 @@ } } } + ctx->usb_event_mode = usb_event_netlink; + return (true); } static bool @@ -92,7 +98,7 @@ devd_addr.sun_family = PF_LOCAL; strlcpy(devd_addr.sun_path, DEVDPIPE, sizeof(devd_addr.sun_path)); - if (connect(devd_pipe, (struct sockaddr *)&devd_addr, + if (connect(ctx->devd_pipe, (struct sockaddr *)&devd_addr, sizeof(devd_addr)) == -1) { close(ctx->devd_pipe); ctx->devd_pipe = -1; @@ -156,91 +162,6 @@ return (0); } -struct nlevent { - const char *name; - const char *subsystem; - const char *type; - const char *data; -}; -#define _OUT(_field) offsetof(struct nlevent, _field) -static struct snl_attr_parser ap_nlevent_get[] = { - { .type = NLSE_ATTR_SYSTEM, .off = _OUT(name), .cb = snl_attr_get_string }, - { .type = NLSE_ATTR_SUBSYSTEM, .off = _OUT(subsystem), .cb = snl_attr_get_string }, - { .type = NLSE_ATTR_TYPE, .off = _OUT(type), .cb = snl_attr_get_string }, - { .type = NLSE_ATTR_DATA, .off = _OUT(data), .cb = snl_attr_get_string }, -}; -#undef _OUT - -SNL_DECLARE_GENL_PARSER(nlevent_get_parser, ap_nlevent_get); - -static void -libusb_event_read(libusb_context *ctx, int rfds) -{ - if (ctx->usb_event_mode == usb_event_netlink) { - struct nlmsghdr *hdr; - struct nlevent ne; - char *ptr; - - if (rfds == 0) - return; - hdr = snl_read_message(&ctx->ss); - if (hdr != NULL && hdr->nlmsg_type != NLMSG_ERROR) { - memset(&ne, 0, sizeof(ne)); - if (!snl_parse_nlmsg(&ctx->ss, hdr, nlevent_get_parser, &ne)) - return; - if (strcmp(ne.subsystem, "DEVICE") != 0) - return; - if (strcmp(ne.type, "ATTACH") == 0) { - - } else if (strcmp(ne.type, "DETACH") == 0) { - - } - } - - return; - } - if (ctx->usb_event_mode == usb_event_devd) { - /* TODO */ - char buf[1024], *ptr; - ssize_t rlen; - - rlen = read(ctx->devd_pipe, buf, sizeof(buf)); - if (rlen == 0 || (rlen < 0 && errno != EWOULDBLOCK)) - return; - if (rlen < 0 && - (ptr = strstr(buf, "system=USB")) != NULL && - (ptr = strstr(ptr, "subsystem=DEVICE")) != NULL) { - if ((ptr = strstr(ptr, "type=ATTACH")) != NULL) { - } else if ((ptr = strstr(ptr, "type=DETACH")) != NULL) { - } - } - return; - } -} - -static void * -libusb_hotplug_poll(void *arg) -{ - fd_set fdset; - libusb_context *ctx = arg; - int nfds, rfds; - - for (;;) { - FD_ZERO(&fdset); - if (ctx->usb_event_mode == usb_event_devd) { - FD_SET(ctx->devd_pipe, &fdset); - nfds = devd_pipe + 1; - } else if (ctx->usb_event_mode == usb_event_netlink) { - FD_SET(ctx->ss.fd, &fdset); - nfds = ctx->ss.fd + 1; - } else { - nfds = 0; - } - rfds = select(nfds, &fdset, NULL, &fdset, NULL); - libusb_event_read(ctx, rfds); - } -} - static void * libusb_hotplug_scan(void *arg) { @@ -251,12 +172,39 @@ libusb_device *temp; libusb_device *adev; libusb_device *bdev; - unsigned do_loop = 1; + struct pollfd pfd[1]; + int timeout = 4000; + int nfds = 0; - while (do_loop) { - usleep(4000000); + if (ctx->usb_event_mode == usb_event_devd) { + pfd[0].fd = ctx->devd_pipe; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + nfds = 1; + } else if (ctx->usb_event_mode == usb_event_netlink) { + pfd[0].fd = ctx->ss.fd; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + nfds = 1; + } else { + nfds = 0; + } + for (;;) { + poll(pfd, nfds, timeout); /* ignore any error */ HOTPLUG_LOCK(ctx); + if (ctx->hotplug_handler == NO_THREAD) { + while ((adev = TAILQ_FIRST(&ctx->hotplug_devs)) != NULL) { + TAILQ_REMOVE(&ctx->hotplug_devs, adev, hotplug_entry); + libusb_unref_device(adev); + } + if (ctx->usb_event_mode == usb_event_devd) + close(ctx->devd_pipe); + else if (ctx->usb_event_mode == usb_event_netlink) + close(ctx->ss.fd); + HOTPLUG_UNLOCK(ctx); + break; + } TAILQ_INIT(&hotplug_devs); @@ -266,7 +214,7 @@ continue; } } else { - do_loop = 0; + break; } /* figure out which devices are gone */