Esempio n. 1
0
void API_EXPORTED libusb_exit(struct libusb_context *ctx)
{
	usbi_dbg("");
	USBI_GET_CONTEXT(ctx);

	if (ctx == usbi_default_context) {
		usbi_mutex_static_lock(&default_context_lock);
		if (--default_context_refcnt > 0) {
			usbi_dbg("not destroying default context");
			usbi_mutex_static_unlock(&default_context_lock);
			return;
		}
		usbi_dbg("destroying default context");
		usbi_default_context = NULL;
		usbi_mutex_static_unlock(&default_context_lock);
	}

	if (!list_empty(&ctx->open_devs))
		usbi_warn(ctx, "application left some devices open");

	usbi_io_exit(ctx);
	if (usbi_backend->exit)
		usbi_backend->exit();

	usbi_mutex_destroy(&ctx->open_devs_lock);
	usbi_mutex_destroy(&ctx->usb_devs_lock);
	free(ctx);
}
Esempio n. 2
0
void linux_udev_hotplug_poll(void)
{
	struct udev_device* udev_dev;

	usbi_mutex_static_lock(&linux_hotplug_lock);
	do {
		udev_dev = udev_monitor_receive_device(udev_monitor);
		if (udev_dev) {
			usbi_dbg("Handling hotplug event from hotplug_poll");
			udev_hotplug_event(udev_dev);
		}
	} while (udev_dev);
	usbi_mutex_static_unlock(&linux_hotplug_lock);
}
Esempio n. 3
0
static void *linux_udev_event_thread_main(void *arg)
{
	struct udev_device* udev_dev;
	struct pollfd fds = {.fd = udev_monitor_fd,
			     .events = POLLIN};

	usbi_dbg("udev event thread entering.");

	while (1 == poll(&fds, 1, -1)) {
		if (NULL == udev_monitor || POLLIN != fds.revents) {
			break;
		}

		usbi_mutex_static_lock(&linux_hotplug_lock);
		udev_dev = udev_monitor_receive_device(udev_monitor);
		if (udev_dev)
			udev_hotplug_event(udev_dev);
		usbi_mutex_static_unlock(&linux_hotplug_lock);
	}

	usbi_dbg("udev event thread exiting");

	return NULL;
}
Esempio n. 4
0
int API_EXPORTED libusb_init(libusb_context **context)
{
	char *dbg = getenv("LIBUSB_DEBUG");
	struct libusb_context *ctx;
	int r = 0;

	usbi_mutex_static_lock(&default_context_lock);
	if (!context && usbi_default_context) {
		usbi_dbg("reusing default context");
		default_context_refcnt++;
		usbi_mutex_static_unlock(&default_context_lock);
		return 0;
	}

	ctx = malloc(sizeof(*ctx));
	if (!ctx) {
		r = LIBUSB_ERROR_NO_MEM;
		goto err_unlock;
	}
	memset(ctx, 0, sizeof(*ctx));

	if (dbg) {
		ctx->debug = atoi(dbg);
		if (ctx->debug)
			ctx->debug_fixed = 1;
	}

	usbi_dbg("libusb-%d.%d.%d%s%s%s",
	         libusb_version_internal.major,
	         libusb_version_internal.minor,
	         libusb_version_internal.micro,
	         libusb_version_internal.rc,
	         libusb_version_internal.describe[0] ? " git:" : "",
	         libusb_version_internal.describe);

	if (usbi_backend->init) {
		r = usbi_backend->init(ctx);
		if (r)
			goto err_free_ctx;
	}

	usbi_mutex_init(&ctx->usb_devs_lock, NULL);
	usbi_mutex_init(&ctx->open_devs_lock, NULL);
	list_init(&ctx->usb_devs);
	list_init(&ctx->open_devs);

	r = usbi_io_init(ctx);
	if (r < 0) {
		if (usbi_backend->exit)
			usbi_backend->exit();
		goto err_destroy_mutex;
	}

	if (context) {
		*context = ctx;
	} else if (!usbi_default_context) {
		usbi_dbg("created default context");
		usbi_default_context = ctx;
		default_context_refcnt++;
	}
	usbi_mutex_static_unlock(&default_context_lock);

	return 0;

err_destroy_mutex:
	usbi_mutex_destroy(&ctx->open_devs_lock);
	usbi_mutex_destroy(&ctx->usb_devs_lock);
err_free_ctx:
	free(ctx);
err_unlock:
	usbi_mutex_static_unlock(&default_context_lock);
	return r;
}
Esempio n. 5
0
static int linux_netlink_read_message(void)
{
	unsigned char buffer[1024];
	struct iovec iov = {.iov_base = buffer, .iov_len = sizeof(buffer)};
	struct msghdr meh = { .msg_iov=&iov, .msg_iovlen=1,
			     .msg_name=&snl, .msg_namelen=sizeof(snl) };
	const char *sys_name = NULL;
	uint8_t busnum, devaddr;
	int detached, r;
	size_t len;

	/* read netlink message */
	memset(buffer, 0, sizeof(buffer));
	len = recvmsg(linux_netlink_socket, &meh, 0);
	if (len < 32) {
		if (errno != EAGAIN)
			usbi_dbg("error recieving message from netlink");
		return -1;
	}

	/* TODO -- authenticate this message is from the kernel or udevd */

	r = linux_netlink_parse(buffer, len, &detached, &sys_name,
				&busnum, &devaddr);
	if (r)
		return r;

	usbi_dbg("netlink hotplug found device busnum: %hhu, devaddr: %hhu, sys_name: %s, removed: %s",
		 busnum, devaddr, sys_name, detached ? "yes" : "no");

	/* signal device is available (or not) to all contexts */
	if (detached)
		linux_hotplug_disconnected(busnum, devaddr, sys_name);
	else
		linux_hotplug_enumerate(busnum, devaddr, sys_name);

	return 0;
}

static void *linux_netlink_event_thread_main(void *arg)
{
	struct pollfd fds = {.fd = linux_netlink_socket,
			     .events = POLLIN};

	/* silence compiler warning */
	(void) arg;

	while (1 == poll(&fds, 1, -1)) {
		if (POLLIN != fds.revents) {
			break;
		}

		usbi_mutex_static_lock(&linux_hotplug_lock);
		linux_netlink_read_message();
		usbi_mutex_static_unlock(&linux_hotplug_lock);
	}

	return NULL;
}

void linux_netlink_hotplug_poll(void)
{
	int r;

	usbi_mutex_static_lock(&linux_hotplug_lock);
	do {
		r = linux_netlink_read_message();
	} while (r == 0);
	usbi_mutex_static_unlock(&linux_hotplug_lock);
}