tmarks
Posts: 13
Joined: Tue Mar 05, 2013 2:34 am

libusb and poll()

Mon Apr 15, 2013 11:17 pm

I've been working on interfacing from user space to the usb core through kernel using libusb because it seems like the most practical way.
The problem I've got at the moment is that using libusb_get_pollfds() and polling the file descriptors that are returned doesn't actually trigger the poll() function, it just timesout.
I've pretty much read through the whole mailing list at libusb sourceforge.net and the developers only reply with "it works", yet I've google searched, github, google code for example code and next to nothing comes up. And if something does come up, the example doesn't work.
I almost believe that since it's a cutdown version of linux, maybe some usb functionality was purposely left out. Either way, anyone here have experience with libusb() and in particular, using poll() with libusb file descriptors.

Thanks

tmarks
Posts: 13
Joined: Tue Mar 05, 2013 2:34 am

Re: libusb and poll()

Mon Apr 15, 2013 11:25 pm

Code snippet

Code: Select all

#include <libusb-1.0/libusb.h>
#include "poll.h"
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

void * Thread(void * threadarg)
{
    struct libusb_pollfd **poll_usb; 
    struct pollfd pollfd_array[20];
    
    //get device handle and claim interface
    //also set up context

    poll_usb = libusb_get_pollfds(ret);  //ret = context
    for (i=0; poll_usb[i] != NULL; i++)
    {
		pollfd_array[i].fd = poll_usb[i]->fd;
		pollfd_array[i].events = poll_usb[i]->events;
    }

    poll_ret = poll(pollfd_array, i, 5000); // timeout of 5 seconds
    //so here poll wont trigger even though i know there is data ready to be received
    //i'm sending data from another thread to the usb device, and it replies but doesn't trigger poll
    if (poll_ret > 0)
    {
        //perform receive functions
    }
    else
    {
        //timeout occurs or pipe error
    }
    
}


tmarks
Posts: 13
Joined: Tue Mar 05, 2013 2:34 am

Re: libusb and poll()

Tue Apr 16, 2013 1:12 am

OK. I've found the answer.

After re-reading the api at http://libusb.sourceforge.net/api-1.0/g ... yncio.html the libusb library does not start any threads for handling events in the background. Hence it is up to the user to call the event handling functions at the correct times.

For this there is three conditions:
1) When an event occurs such as read/write using a libusb_fill_####_()
2) When a timeout occurs for a read/write using a libusb_fill_####_()
3) When an event handling is required at a specified time

So the simplest way to overcome this is to create a thread which calls libusb_handle_events(). This function does block until its needed to process, thus having a separate thread for handling this function should not take up too much processing power.

I think the proper way is to integrate libusb_handle_events_timeout() into your application where it is called at all when either of those above 3 conditions occur.

Code: Select all

void * MyLibusbEventsHandler(void * threadarg)
{
	mymutex * args = (Mymutex *) threadarg;
	
	while (*(args->running))
    {
        pthread_mutex_lock(&args->handle_mutex);
        printf("Handle: Handle thread sleeping.\n");
        pthread_cond_wait(&args->handle_condition, &args->handle_mutex);
		pthread_mutex_unlock(&args->handle_mutex);
        
        printf("Handle: Handle thread started.\n");
		
		while (args->device)
		{
			libusb_handle_events(args->context);
			printf("Handle: Events detected.\n");
		}
    }
}
So the above example shows how I've simply implemented a thread which will loop continuously until:
1) there is no device available for handling eg. device disconnected (args->device)
2) the user is closing the program, thus manually removes the device parameter and turns args->running off

So in short, you HAVE to include some sort of calling to libusb_handle_events() during processing. This will handle your file descriptors also.

Return to “C/C++”