Launchpad Update

I am almost done rewriting my launchpad code so that it can be run without a kernel module. Instead, I’ll be using libusb, which is a reasonably common and cross-platform library for interacting with USB devices.

I’m having a couple issues with callbacks and polling, but I’m making pretty steady progress, and should have a stable version to post pretty soon.

The header for interactions with the launchpad is going to look like this:

typedef void(*launchpad_callback)(unsigned char* data, size_t len, void* user_data);

struct launchpad_handle* launchpad_register(launchpad_callback e, void* user_data);

int launchpad_write(struct launchpad_handle *dp, unsigned char* data, size_t len);
int launchpad_poll(struct pollfd* descriptors, size_t num);

void launchpad_deregister(struct launchpad_handle* dp);

You start by writing your callback function, which will be called whenever new data is available from the launchpad, or a write to the launchpad completes. Then register that to start receiving notifications. Call write to send data to the device, and use the launchpad_poll in your main loop, which externally will act as a standard system poll() call, but also handles device events.

It’s worth noting that you can play with the kernel module already by downloading the code from the project page

On the technical side, I’ve worked through a couple issues that took a bit more debugging than I really wanted, so I figured I’d post them here:

The correct formulation forĀ libusb_lock_events appears to be put immediately before your call to poll(), and you should unlock immediately afterwards. If you lock events for the entire access time, you will find that although you’re polling, the reads and writes you initiate never get processed.

If libusb_submit_transfer() is failing with code -1, it’s possibly a IO error, meaning that you don’t have your endpoint correctly defined. For me the issue was that although my output endpoint was an interrupt type, it actually was registered as a bulk-data type. (that is, it’s address was 0x02 rather than 0x01. Checking your endpoints with lsusb -v will let you check what the actual endpoints should be.)