Browse files

Added support for USB control transfer

Device.controlTransfer(bytesToRead, bmRequestType, bRequest, 0, 0, function(data) {}) works as expected.
data will be a node.js buffer object which makes byte manipulation easy.
I update the Kinect example to read the accelerometer axes from the device (taken from ladyada.net/leran/diykinect).
  • Loading branch information...
1 parent 7b78e10 commit 59d3d997aa07d0a77e03004f76716de2d3a66d60 Christopher Klein committed Mar 24, 2012
Showing with 77 additions and 27 deletions.
  1. +1 −1 Makefile
  2. +18 −0 examples/kinect/kinect.js
  3. +38 −12 src/bindings.h
  4. +6 −3 src/device.cc
  5. +1 −0 src/device.h
  6. +9 −7 src/node_usb.h
  7. +1 −1 usb.js
  8. +3 −3 wscript
View
2 Makefile
@@ -1,5 +1,5 @@
make:
- node-waf configure clean build; node tests/node-usb-test.js
+ node-waf -v configure clean build; node tests/node-usb-test.js
debug:
node-waf configure --debug=true clean build; node tests/node-usb-test.js
View
18 examples/kinect/kinect.js
@@ -46,6 +46,7 @@ http.createServer(function(req, res) {
req.on('data', function(data) { incomingBody += data; });
req.on('end', function() {
var postData = qs.parse(incomingBody);
+ var bulkOutput = "<strong>no data</strong>";
switch (req.url) {
case '/updateLed':
@@ -78,6 +79,22 @@ console.log("Angle set to " + angle);
});
break;
+ case '/getCoordinates':
+ motor.controlTransfer(10 /* read 10 bytes */, 0xC0 /* bmRequestType */, 0x32 /* bRequest */, 0, 0, function(data) {
+ for (var i = 0; i < 10; i++) {
+ console.log("buffer[" + i + "]: " + data[i])
+ }
+ console.log("Accelerometer axis:")
+ var x = ((data[2] << 8) | data[3]), y = ((data[4] << 8) | data[5]), z = ((data[6] << 8) | data[7])
+ x = (x + Math.pow(2,15)) % Math.pow(2,16) - Math.pow(2,15)
+ y = (y + Math.pow(2,15)) % Math.pow(2,16) - Math.pow(2,15)
+ z = (z + Math.pow(2,15)) % Math.pow(2,16) - Math.pow(2,15)
+
+ console.log(" X:" + x)
+ console.log(" Y:" + y)
+ console.log(" Z:" + z)
+ })
+ break;
}
});
@@ -91,6 +108,7 @@ console.log("Angle set to " + angle);
html += "</select><input type='submit' value='change color' /></form>";
html += "<form method='post' action='updateAngle'>";
html += "Set angle (-31 - +31) <input type='text' name='angle' size='2' /><input type='submit' value='change angle'/></form>";
+ html += "<a href='/getCoordinates'>Retrieve coordinates from Kinect via control transfer</a>";
html += "</body></html>";
res.write(html);
View
50 src/bindings.h
@@ -76,22 +76,25 @@
} \
VARNAME->callback = Persistent<Function>::New(callback);
+#define EIO_HANDLE_ERROR(VARNAME) \
+ if(VARNAME->errsource) { \
+ Handle<Object> error = Object::New(); \
+ error->Set(V8SYM("error_source"), V8STR(VARNAME->errsource)); \
+ error->Set(V8SYM("error_code"), Uint32::New(VARNAME->errcode)); \
+ Local<Value> argv[1]; \
+ argv[0] = Local<Value>::New(scope.Close(error)); \
+ TryCatch try_catch; \
+ VARNAME->callback->Call(Context::GetCurrent()->Global(), 1, argv); \
+ if (try_catch.HasCaught()) { \
+ FatalException(try_catch); \
+ } \
+ }
+
#define EIO_AFTER(VARNAME, SELF) \
uv_unref(uv_default_loop()); \
if (!VARNAME->callback.IsEmpty()) { \
HandleScope scope; \
- Handle<Object> error = Object::New(); \
- if(VARNAME->errsource) { \
- error->Set(V8SYM("error_source"), V8STR(VARNAME->errsource)); \
- } \
- error->Set(V8SYM("error_code"), Uint32::New(VARNAME->errcode)); \
- Local<Value> argv[1]; \
- argv[0] = Local<Value>::New(scope.Close(error)); \
- TryCatch try_catch; \
- VARNAME->callback->Call(Context::GetCurrent()->Global(), 1, argv); \
- if (try_catch.HasCaught()) { \
- FatalException(try_catch); \
- } \
+ EIO_HANDLE_ERROR(VARNAME) \
VARNAME->callback.Dispose(); \
}\
delete req;\
@@ -100,6 +103,28 @@
#define TRANSFER_REQUEST_FREE(STRUCT, SELF)\
EIO_CAST(STRUCT, transfer_req)\
EIO_AFTER(transfer_req, SELF)\
+ free(transfer_req);
+
+#define TRANSFER_REQUEST_FREE_WITH_DATA(STRUCT, SELF)\
+ EIO_CAST(STRUCT, transfer_req)\
+ uv_unref(uv_default_loop()); \
+ if (!transfer_req->callback.IsEmpty()) { \
+ HandleScope scope; \
+ EIO_HANDLE_ERROR(transfer_req) \
+ if (!transfer_req->errsource) {\
+ Buffer *result = Buffer::New((char *)transfer_req->data, transfer_req->bytesTransferred); \
+ Local<Value> argv[1]; \
+ argv[0] = Local<Value>::New(result->handle_); \
+ TryCatch try_catch; \
+ transfer_req->callback->Call(Context::GetCurrent()->Global(), 1, argv); \
+ if (try_catch.HasCaught()) { \
+ FatalException(try_catch); \
+ } \
+ }\
+ transfer_req->callback.Dispose(); \
+ }\
+ delete req;\
+ transfer_req->SELF->Unref();\
free(transfer_req);\
#define INIT_TRANSFER_CALL(MINIMUM_ARG_LENGTH, CALLBACK_ARG_IDX, TIMEOUT_ARG_IDX) \
@@ -222,6 +247,7 @@ namespace NodeUsb {
err = "Unknown error";
break;
}
+
// convert err to const char* with help of c_str()
obj->Set(NODE_PSYMBOL("msg"), String::New(err.c_str()));
return e;
View
9 src/device.cc
@@ -391,13 +391,16 @@ namespace NodeUsb {
Device * self = ct_req->device;
libusb_device_handle * handle = self->device_container->handle;
- ct_req->errcode = libusb_control_transfer(handle, ct_req->bmRequestType, ct_req->bRequest, ct_req->wValue, ct_req->wIndex, ct_req->data, ct_req->wLength, ct_req->timeout);
- if (ct_req->errcode < LIBUSB_SUCCESS) {
+ ct_req->bytesTransferred = libusb_control_transfer(handle, ct_req->bmRequestType, ct_req->bRequest, ct_req->wValue, ct_req->wIndex, ct_req->data, ct_req->wLength, ct_req->timeout);
+
+ if (ct_req->bytesTransferred < LIBUSB_SUCCESS) {
+ ct_req->errcode = ct_req->bytesTransferred;
+ ct_req->bytesTransferred = 0;
ct_req->errsource = "controlTransfer";
}
}
void Device::EIO_After_ControlTransfer(uv_work_t *req) {
- TRANSFER_REQUEST_FREE(control_transfer_request, device)
+ TRANSFER_REQUEST_FREE_WITH_DATA(control_transfer_request, device)
}
}
View
1 src/device.h
@@ -13,6 +13,7 @@ namespace NodeUsb {
struct nodeusb_transfer:device_request {
unsigned char *data;
unsigned int timeout;
+ uint16_t bytesTransferred;
};
struct control_transfer_request:nodeusb_transfer {
View
16 src/node_usb.h
@@ -1,23 +1,25 @@
#ifndef SRC_NODE_USB_H
#define SRC_NODE_USB_H
-#include <libusb.h>
-#include <v8.h>
+#include <stdlib.h>
+#include <unistd.h>
#include <string.h>
+#include <stdio.h>
#include <errno.h>
#include <iostream>
-#include <stdio.h>
-#include <unistd.h>
+#include <cstring>
+#include <string>
+#include <cstdlib>
+
+#include <libusb.h>
+#include <v8.h>
#include <node.h>
#include <node_version.h>
#include <node_buffer.h>
#include <uv.h>
#include <uv-private/ev.h>
-#include <cstring>
-#include <string>
-#include <cstdlib>
#define NODE_USB_VERSION "0.1"
View
2 usb.js
@@ -1,7 +1,7 @@
/**
* Expose complete node-usb binding to node.js
*/
-var binding = require("usb_bindings");
+var binding = require("./usb_bindings");
exports.create = function() {
var usbInstance = new binding.Usb();
View
6 wscript
@@ -28,7 +28,7 @@ def build(bld):
obj.target = 'usb_bindings'
obj.source = './src/node_usb.cc ./src/usb.cc ./src/device.cc ./src/interface.cc ./src/endpoint.cc'
obj.includes = bld.env['CPPPATH_USB10']
- obj.lib = bld.env['LIB_USB10']
+ obj.uselib = ["USB10"]
obj.name = "node-usb"
obj.defines = ['NODE_USB_REVISION="' + REVISION + '"']
@@ -38,5 +38,5 @@ def build(bld):
def shutdown():
t = 'usb_bindings.node';
- if exists('build/default/' + t) and not exists(t):
- symlink('build/default/' + t, t)
+ if exists('build/Release/' + t) and not exists(t):
+ symlink('build/Release/' + t, t)

0 comments on commit 59d3d99

Please sign in to comment.