I’ve been playing with the Processing language (http://processing.org) a little bit and liking it so far. For anyone not familiar, it’s a Java-based rapid-prototyping language that includes very friendly libraries for graphics, sound, video and select hardware (e.g. serial port). One thing I couldn’t find much info on was talking to arbitrary USB devices (not USB-to-serial based gadgets, but sending and receiving raw packet-level data).
Anyway, I found a solution that works in Processing with only minimal tweaking. You need:
Processing (of course) – http://www.processing.org
libusb or libusb-win32 – http://libusb-win32.sourceforge.net (Windows) or http://libusb.wiki.sourceforge.net/ (Linux)
Libusb Java wrapper – http://libusbjava.sourceforge.net/wp/
I only tried this on Windows so far, so the following assumes a Windows installation.
(I know, wrappers upon wrappers. So in the end you end up with device -> OS -> libusb -> libusbjava native DLL -> libusbjava JNI wrapper -> Processing. Probably not the most efficient approach in the world, but in the era of multi-GHz machines I’m not sweating too hard about it :-)
Follow the author’s recommendations on setting up libusb-win32 for your device, if it’s not already been done. Then, (for Windows users) extract the LibusbJava.dll file and drop it somewhere Processing/Windows can find it. The author recommends \Windows\System or equivalent; if this seems a bit forward, dropping it in the same directory as processing.exe works fine too.
Finally, making the library appear for Processing: create a new folder(-nest) for it in Processing’s libraries folder (blahblah\processing-0135\libraries\libusbjava\library), and drop the .jar file in it. Rename it to something more sane; Processing doesn’t seem to like all those extra dots and numerals. After renaming the .jar file sanely and restarting Processing, it will appear in the Sketch->Import Library menu. Clicking on the menu item automagically fishes out the correct class names and adds the appropriate (import…) lines to your sketch. From here on out, programming for the libusbjava wrapper appears to follow the actual libusb API pretty closely.
Here’s the program I tested it with. All it does is connect to a Rez/Drmn trance vibrator, send a USB packet to turn the motor on at about 2/3 intensity, then exit.
import ch.ntb.usb.testApp.*; // these four lines were automatically added by clicking it
import ch.ntb.usb.*; // on Processing's Sketch -> Import Library menu item
import ch.ntb.usb.usbView.*; // ...
import ch.ntb.usb.logger.*; // Some of these can probably be removed safely.
void setup()
{
noLoop();
}
void draw()
{
LibusbJava.usb_init(); // required inits for libusb-win32
LibusbJava.usb_find_busses(); //
LibusbJava.usb_find_devices(); //
// retrieve a object tree representing the bus with its devices and
// descriptors
Usb_Bus bus = LibusbJava.usb_get_busses();
// Find a specific USB device on the bus (by its VID/PID) and return a handle to the device in 'dev'
// This diverges a bit from native libusb-win32 code in that you don't have to loop through all the devices/busses searching for it.
Device dev = USB.getDevice((short) 0x0b49, (short) 0x064f); // VID/PID combination of Drmn' Trance Vibe device
// Note: Since this is just a quick n dirty "hey, is this possible?" test, I've added no error checking whatsoever.
// For anything more than a tightly-controlled quick hack / demo, you will want to do so!! (for starters, check if the device was found at all...)
try {
// data to write to the device. I don't want to write any data, so leaving this array empty.
byte[] data = new byte[] {};
// data read from the device
byte[] readData = new byte[data.length];
// open the device with configuration 1, interface 0 and without
// altinterface
// this will initialise Libusb for you
dev.open(1, 0, -1);
// ^^ Note, this may also diverge from native libusb-win32; I've never seen the choice of "-1" for alt. interface before (I assume it's interpreted as "any/all/none/don't-care"), but it seems to work.
// This device uses Control messages on endpoint 0. The following packet turns ON the motor at about 2/3 intensity (0xAA).
// Fields are: Request type (0x41-Out+Write), bRequest, WValue, wIndex, byte[] data, size, timeout, bool reopenOnTimeout
dev.controlMsg(0x41, 0x00, 0xAAAA, 0x0000, data, 0, 1000, false);
// The "reopenOnTimeout" field is a new one. It sounds either flaky-hardware-friendly or extremely dangerous.
// ok, motor turned on! I'm satisfied that you can control arbitrary USB devices from Processing at the raw (bulk/interrupt) packet level, so this is as far as I go for now.
// close the device
dev.close();
} catch (USBException e) {
// if an exception occures during connect or read/write an exception
// is thrown
e.printStackTrace();
}
}
Leave a Reply