예제 #1
0
int linux_netlink_start_event_monitor(void)
{
    int socktype = SOCK_RAW;
    int ret;

    snl.nl_groups = KERNEL;

#if defined(SOCK_CLOEXEC)
    socktype |= SOCK_CLOEXEC;
#endif
#if defined(SOCK_NONBLOCK)
    socktype |= SOCK_NONBLOCK;
#endif

    linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
    if (-1 == linux_netlink_socket && EINVAL == errno) {
        linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
    }

    if (-1 == linux_netlink_socket) {
        return LIBUSB_ERROR_OTHER;
    }

    ret = set_fd_cloexec_nb (linux_netlink_socket);
    if (0 != ret) {
        close (linux_netlink_socket);
        linux_netlink_socket = -1;
        return LIBUSB_ERROR_OTHER;
    }

    ret = bind(linux_netlink_socket, (struct sockaddr *) &snl, sizeof(snl));
    if (0 != ret) {
        close(linux_netlink_socket);
        return LIBUSB_ERROR_OTHER;
    }

    /* TODO -- add authentication */
    /* setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); */

    ret = usbi_pipe(netlink_control_pipe);
    if (ret) {
        usbi_err(NULL, "could not create netlink control pipe");
        close(linux_netlink_socket);
        return LIBUSB_ERROR_OTHER;
    }

    ret = pthread_create(&libusb_linux_event_thread, NULL, linux_netlink_event_thread_main, NULL);
    if (0 != ret) {
        close(netlink_control_pipe[0]);
        close(netlink_control_pipe[1]);
        close(linux_netlink_socket);
        return LIBUSB_ERROR_OTHER;
    }

    return LIBUSB_SUCCESS;
}
예제 #2
0
int event_init_platform(void) {
	int phase = 0;

	// create read set
	if (event_reserve_socket_set(&_socket_read_set, 32) < 0) {
		log_error("Could not create socket read set: %s (%d)",
		          get_errno_name(errno), errno);

		goto cleanup;
	}

	phase = 1;

	// create write set
	if (event_reserve_socket_set(&_socket_write_set, 32) < 0) {
		log_error("Could not create socket write set: %s (%d)",
		          get_errno_name(errno), errno);

		goto cleanup;
	}

	phase = 2;

	// create error set
	if (event_reserve_socket_set(&_socket_error_set, 32) < 0) {
		log_error("Could not create socket error set: %s (%d)",
		          get_errno_name(errno), errno);

		goto cleanup;
	}

	phase = 3;

	// create stop pipe
	if (pipe_create(&_stop_pipe, 0) < 0) {
		log_error("Could not create stop pipe: %s (%d)",
		          get_errno_name(errno), errno);

		goto cleanup;
	}

	phase = 4;

	if (event_add_source(_stop_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC,
	                     EVENT_READ, NULL, NULL) < 0) {
		goto cleanup;
	}

	phase = 5;

	// create USB poll thread
	_usb_poll_running = false;
	_usb_poll_stuck = false;

	if (usbi_pipe(_usb_poll_suspend_pipe) < 0) {
		log_error("Could not create USB suspend pipe");

		goto cleanup;
	}

	phase = 6;

	if (pipe_create(&_usb_poll_ready_pipe, 0) < 0) {
		log_error("Could not create USB ready pipe: %s (%d)",
		          get_errno_name(errno), errno);

		goto cleanup;
	}

	phase = 7;

	if (array_create(&_usb_poll_pollfds, 32, sizeof(struct usbi_pollfd), true) < 0) {
		log_error("Could not create USB pollfd array: %s (%d)",
		          get_errno_name(errno), errno);

		goto cleanup;
	}

	phase = 8;

	if (semaphore_create(&_usb_poll_resume) < 0) {
		log_error("Could not create USB resume semaphore: %s (%d)",
		          get_errno_name(errno), errno);

		goto cleanup;
	}

	phase = 9;

	if (semaphore_create(&_usb_poll_suspend) < 0) {
		log_error("Could not create USB suspend semaphore: %s (%d)",
		          get_errno_name(errno), errno);

		goto cleanup;
	}

	phase = 10;

cleanup:
	switch (phase) { // no breaks, all cases fall through intentionally
	case 9:
		semaphore_destroy(&_usb_poll_suspend);

	case 8:
		semaphore_destroy(&_usb_poll_resume);

	case 7:
		pipe_destroy(&_usb_poll_ready_pipe);

	case 6:
		usbi_close(_usb_poll_suspend_pipe[0]);
		usbi_close(_usb_poll_suspend_pipe[1]);

	case 5:
		event_remove_source(_stop_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC);

	case 4:
		pipe_destroy(&_stop_pipe);

	case 3:
		free(_socket_error_set);

	case 2:
		free(_socket_write_set);

	case 1:
		free(_socket_read_set);

	default:
		break;
	}

	return phase == 10 ? 0 : -1;
}
예제 #3
0
int linux_udev_start_event_monitor(void)
{
	int r;

	assert(udev_ctx == NULL);
	udev_ctx = udev_new();
	if (!udev_ctx) {
		usbi_err(NULL, "could not create udev context");
		goto err;
	}

	udev_monitor = udev_monitor_new_from_netlink(udev_ctx, "udev");
	if (!udev_monitor) {
		usbi_err(NULL, "could not initialize udev monitor");
		goto err_free_ctx;
	}

	r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", 0);
	if (r) {
		usbi_err(NULL, "could not initialize udev monitor filter for \"usb\" subsystem");
		goto err_free_monitor;
	}

	if (udev_monitor_enable_receiving(udev_monitor)) {
		usbi_err(NULL, "failed to enable the udev monitor");
		goto err_free_monitor;
	}

	udev_monitor_fd = udev_monitor_get_fd(udev_monitor);

	/* Some older versions of udev are not non-blocking by default,
	 * so make sure this is set */
	r = fcntl(udev_monitor_fd, F_GETFL);
	if (r == -1) {
		usbi_err(NULL, "getting udev monitor fd flags (%d)", errno);
		goto err_free_monitor;
	}
	r = fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK);
	if (r) {
		usbi_err(NULL, "setting udev monitor fd flags (%d)", errno);
		goto err_free_monitor;
	}

	r = usbi_pipe(udev_control_pipe);
	if (r) {
		usbi_err(NULL, "could not create udev control pipe");
		goto err_free_monitor;
	}

	r = pthread_create(&linux_event_thread, NULL, linux_udev_event_thread_main, NULL);
	if (r) {
		usbi_err(NULL, "creating hotplug event thread (%d)", r);
		goto err_close_pipe;
	}

	return LIBUSB_SUCCESS;

err_close_pipe:
	close(udev_control_pipe[0]);
	close(udev_control_pipe[1]);
err_free_monitor:
	udev_monitor_unref(udev_monitor);
	udev_monitor = NULL;
	udev_monitor_fd = -1;
err_free_ctx:
	udev_unref(udev_ctx);
err:
	udev_ctx = NULL;
	return LIBUSB_ERROR_OTHER;
}