Skip to content

Commit

Permalink
extra_length value is now used
Browse files Browse the repository at this point in the history
- added device.extra_length property
- added [device|interface|endpoint].getExtraData() method
- idx constructor parameters are now passed as uint32_t
- fixed memory leak
- endpoint descriptor is now detected in Endpoint class by idx of endpoint
  • Loading branch information
Christopher Klein committed Dec 14, 2010
1 parent 5093e70 commit 71bca45
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 20 deletions.
23 changes: 23 additions & 0 deletions examples/lsusb.js
Expand Up @@ -27,6 +27,23 @@ function toByteArray(_i) {
return array.reverse(); return array.reverse();
} }


function get_extra_data(obj) {
var data = obj.getExtraData(), r = "";

if (!max_bytes) {
var max_bytes = 5;
}

for (var i = 0; (i < data.length && i < max_bytes); i++) {
r += "0x" + pad(toHex(data[i]), 2, 0) + " ";
}

if (i < data.length) {
r += "(" + (data.length - i) + " bytes more)";
}

return r;
}


function pad(v, len, fill) { function pad(v, len, fill) {
var s = v.toString(); var s = v.toString();
Expand Down Expand Up @@ -74,6 +91,8 @@ for (var i = 0; i < devices.length; i++) {
console.log(" iConfiguration " + cd.iConfiguration); console.log(" iConfiguration " + cd.iConfiguration);
console.log(" bmAttributes 0x" + toHex(cd.bmAttributes)); console.log(" bmAttributes 0x" + toHex(cd.bmAttributes));
console.log(" MaxPower " + cd.MaxPower); console.log(" MaxPower " + cd.MaxPower);
console.log(" __extra_length " + cd.extra_length);
console.log(" __extra_data (first 5b) " + get_extra_data(device));


var interfaces = device.getInterfaces(); var interfaces = device.getInterfaces();


Expand All @@ -89,6 +108,8 @@ for (var i = 0; i < devices.length; i++) {
console.log(" bInterfaceSubClass " + interface.bInterfaceSubClass); console.log(" bInterfaceSubClass " + interface.bInterfaceSubClass);
console.log(" bInterfaceProtocol " + interface.bInterfaceProtocol); console.log(" bInterfaceProtocol " + interface.bInterfaceProtocol);
console.log(" iInterface " + interface.iInterface); console.log(" iInterface " + interface.iInterface);
console.log(" __extra_length " + interface.extra_length);
console.log(" __extra_data (first 5b) " + get_extra_data(interface));


var endpoints = interface.getEndpoints(); var endpoints = interface.getEndpoints();


Expand All @@ -101,6 +122,8 @@ for (var i = 0; i < devices.length; i++) {
console.log(" bmAttributes " + endpoint.bmAttributes); console.log(" bmAttributes " + endpoint.bmAttributes);
console.log(" wMaxPacketSize 0x" + pad(toHex(endpoint.wMaxPacketSize), 4, "0")); console.log(" wMaxPacketSize 0x" + pad(toHex(endpoint.wMaxPacketSize), 4, "0"));
console.log(" bInterval " + endpoint.bInterval); console.log(" bInterval " + endpoint.bInterval);
console.log(" __extra_length " + endpoint.extra_length);
console.log(" __extra_data (first 5b) " + get_extra_data(endpoint));
} }
} }
} }
Expand Down
19 changes: 18 additions & 1 deletion src/device.cc
Expand Up @@ -35,6 +35,7 @@ namespace NodeUsb {
NODE_SET_PROTOTYPE_METHOD(t, "getDeviceDescriptor", Device::GetDeviceDescriptor); NODE_SET_PROTOTYPE_METHOD(t, "getDeviceDescriptor", Device::GetDeviceDescriptor);
NODE_SET_PROTOTYPE_METHOD(t, "getConfigDescriptor", Device::GetConfigDescriptor); NODE_SET_PROTOTYPE_METHOD(t, "getConfigDescriptor", Device::GetConfigDescriptor);
NODE_SET_PROTOTYPE_METHOD(t, "getInterfaces", Device::GetInterfaces); NODE_SET_PROTOTYPE_METHOD(t, "getInterfaces", Device::GetInterfaces);
NODE_SET_PROTOTYPE_METHOD(t, "getExtraData", Device::GetExtraData);


// Make it visible in JavaScript // Make it visible in JavaScript
target->Set(String::NewSymbol("Device"), t->GetFunction()); target->Set(String::NewSymbol("Device"), t->GetFunction());
Expand Down Expand Up @@ -176,7 +177,7 @@ namespace NodeUsb {


// TODO: Read-Only // TODO: Read-Only
#define LIBUSB_CONFIG_DESCRIPTOR_STRUCT_TO_V8(name) \ #define LIBUSB_CONFIG_DESCRIPTOR_STRUCT_TO_V8(name) \
r->Set(V8STR(#name), Integer::New((*self->device_container->config_descriptor).name)); r->Set(V8STR(#name), Uint32::New((*self->device_container->config_descriptor).name));


/** /**
* Returns configuration descriptor structure * Returns configuration descriptor structure
Expand Down Expand Up @@ -209,6 +210,22 @@ namespace NodeUsb {
return scope.Close(r); return scope.Close(r);
} }


Handle<Value> Device::GetExtraData(const Arguments& args) {
LOCAL(Device, self, args.This())

int m = (*self->device_container->config_descriptor).extra_length;

Local<Array> r = Array::New(m);

for (int i = 0; i < m; i++) {
uint32_t c = (*self->device_container->config_descriptor).extra[i];

r->Set(i, Uint32::New(c));
}

return scope.Close(r);
}

Handle<Value> Device::GetInterfaces(const Arguments& args) { Handle<Value> Device::GetInterfaces(const Arguments& args) {
LOCAL(Device, self, args.This()) LOCAL(Device, self, args.This())
#if defined(__APPLE__) && defined(__MACH__) #if defined(__APPLE__) && defined(__MACH__)
Expand Down
1 change: 1 addition & 0 deletions src/device.h
Expand Up @@ -32,6 +32,7 @@ namespace NodeUsb {
static int EIO_Reset(eio_req *req); static int EIO_Reset(eio_req *req);
static Handle<Value> GetConfigDescriptor(const Arguments& args); static Handle<Value> GetConfigDescriptor(const Arguments& args);
static Handle<Value> GetDeviceDescriptor(const Arguments& args); static Handle<Value> GetDeviceDescriptor(const Arguments& args);
static Handle<Value> GetExtraData(const Arguments& args);
static Handle<Value> GetInterfaces(const Arguments& args); static Handle<Value> GetInterfaces(const Arguments& args);
}; };
} }
Expand Down
35 changes: 27 additions & 8 deletions src/endpoint.cc
Expand Up @@ -4,13 +4,14 @@
namespace NodeUsb { namespace NodeUsb {
Persistent<FunctionTemplate> Endpoint::constructor_template; Persistent<FunctionTemplate> Endpoint::constructor_template;


Endpoint::Endpoint(nodeusb_device_container* _device_container, libusb_endpoint_descriptor* _endpoint_descriptor) { Endpoint::Endpoint(nodeusb_device_container* _device_container, const libusb_endpoint_descriptor* _endpoint_descriptor, uint32_t _idx_endpoint) {
device_container = _device_container; device_container = _device_container;
descriptor = _endpoint_descriptor; descriptor = _endpoint_descriptor;
// if bit[7] of endpoint address is set => ENDPOINT_IN (device to host), else: ENDPOINT_OUT (host to device) // if bit[7] of endpoint address is set => ENDPOINT_IN (device to host), else: ENDPOINT_OUT (host to device)
endpoint_type = (descriptor->bEndpointAddress & (1 << 7)) ? (LIBUSB_ENDPOINT_IN) : (LIBUSB_ENDPOINT_OUT); endpoint_type = (descriptor->bEndpointAddress & (1 << 7)) ? (LIBUSB_ENDPOINT_IN) : (LIBUSB_ENDPOINT_OUT);
// bit[0] and bit[1] of bmAttributes masks transfer_type; 3 = 0000 0011 // bit[0] and bit[1] of bmAttributes masks transfer_type; 3 = 0000 0011
transfer_type = (3 & descriptor->bmAttributes); transfer_type = (3 & descriptor->bmAttributes);
idx_endpoint = _idx_endpoint;
} }


Endpoint::~Endpoint() { Endpoint::~Endpoint() {
Expand Down Expand Up @@ -41,6 +42,7 @@ namespace NodeUsb {
instance_template->SetAccessor(V8STR("__maxPacketSize"), Endpoint::MaxPacketSizeGetter); instance_template->SetAccessor(V8STR("__maxPacketSize"), Endpoint::MaxPacketSizeGetter);


// methods exposed to node.js // methods exposed to node.js
NODE_SET_PROTOTYPE_METHOD(t, "getExtraData", Endpoint::GetExtraData);


// Make it visible in JavaScript // Make it visible in JavaScript
target->Set(String::NewSymbol("Endpoint"), t->GetFunction()); target->Set(String::NewSymbol("Endpoint"), t->GetFunction());
Expand All @@ -52,24 +54,25 @@ namespace NodeUsb {
DEBUG("New Endpoint object created") DEBUG("New Endpoint object created")


// need libusb_device structure as first argument // need libusb_device structure as first argument
if (args.Length() != 2 || !args[0]->IsExternal() || !args[1]->IsExternal()) { if (args.Length() != 4 || !args[0]->IsExternal() || !args[1]->IsUint32() || !args[2]->IsUint32()|| !args[3]->IsUint32()) {
THROW_BAD_ARGS("Device::New argument is invalid. [object:external:libusb_device, object:external:libusb_external_descriptor]!") THROW_BAD_ARGS("Device::New argument is invalid. [object:external:libusb_device, uint32_t:idx_interface, uint32_t:idx_alt_setting, uint32_t:idx_endpoint]!")
} }


// make local value reference to first parameter // make local value reference to first parameter
Local<External> refDeviceContainer = Local<External>::Cast(args[0]); Local<External> refDeviceContainer = Local<External>::Cast(args[0]);
Local<External> refEndpointDescriptor = Local<External>::Cast(args[1]); uint32_t idxInterface = args[1]->Uint32Value();
uint32_t idxAltSetting = args[2]->Uint32Value();
uint32_t idxEndpoint = args[3]->Uint32Value();


// cast local reference to local
nodeusb_device_container *deviceContainer = static_cast<nodeusb_device_container*>(refDeviceContainer->Value()); nodeusb_device_container *deviceContainer = static_cast<nodeusb_device_container*>(refDeviceContainer->Value());
libusb_endpoint_descriptor *libusbEndpointDescriptor = static_cast<libusb_endpoint_descriptor*>(refEndpointDescriptor->Value()); const libusb_endpoint_descriptor *libusbEndpointDescriptor = &(((*deviceContainer->config_descriptor).interface[idxInterface]).altsetting[idxAltSetting]).endpoint[idxEndpoint];


// create new Endpoint object // create new Endpoint object
Endpoint *endpoint = new Endpoint(deviceContainer, libusbEndpointDescriptor); Endpoint *endpoint = new Endpoint(deviceContainer, libusbEndpointDescriptor, idxEndpoint);
// initalize handle // initalize handle


#define LIBUSB_ENDPOINT_DESCRIPTOR_STRUCT_TO_V8(name) \ #define LIBUSB_ENDPOINT_DESCRIPTOR_STRUCT_TO_V8(name) \
args.This()->Set(V8STR(#name), Integer::New(endpoint->descriptor->name)); args.This()->Set(V8STR(#name), Uint32::New(endpoint->descriptor->name));
LIBUSB_ENDPOINT_DESCRIPTOR_STRUCT_TO_V8(bLength) LIBUSB_ENDPOINT_DESCRIPTOR_STRUCT_TO_V8(bLength)
LIBUSB_ENDPOINT_DESCRIPTOR_STRUCT_TO_V8(bDescriptorType) LIBUSB_ENDPOINT_DESCRIPTOR_STRUCT_TO_V8(bDescriptorType)
LIBUSB_ENDPOINT_DESCRIPTOR_STRUCT_TO_V8(bEndpointAddress) LIBUSB_ENDPOINT_DESCRIPTOR_STRUCT_TO_V8(bEndpointAddress)
Expand Down Expand Up @@ -116,6 +119,22 @@ namespace NodeUsb {
return scope.Close(Integer::New(r)); return scope.Close(Integer::New(r));
} }


Handle<Value> Endpoint::GetExtraData(const Arguments& args) {
LOCAL(Endpoint, self, args.This())

long m = (*self->descriptor).extra_length;

Local<Array> r = Array::New(m);

for (int i = 0; i < m; i++) {
uint32_t c = (*self->descriptor).extra[i];

r->Set(i, Uint32::New(c));
}

return scope.Close(r);
}

void Callback::DispatchAsynchronousUsbTransfer(libusb_transfer *_transfer) { void Callback::DispatchAsynchronousUsbTransfer(libusb_transfer *_transfer) {
const int num_args = 2; const int num_args = 2;
Local<Value> argv[num_args]; Local<Value> argv[num_args];
Expand Down
10 changes: 6 additions & 4 deletions src/endpoint.h
Expand Up @@ -12,14 +12,15 @@ namespace NodeUsb {
static void Initalize(Handle<Object> target); static void Initalize(Handle<Object> target);
static Persistent<FunctionTemplate> constructor_template; static Persistent<FunctionTemplate> constructor_template;
// Dispatcher / callback handler must be static // Dispatcher / callback handler must be static
Endpoint(nodeusb_device_container*, libusb_endpoint_descriptor*); Endpoint(nodeusb_device_container*, const libusb_endpoint_descriptor*, uint32_t);
~Endpoint(); ~Endpoint();
protected: protected:
// members // members
struct nodeusb_device_container *device_container; struct nodeusb_device_container *device_container;
struct libusb_endpoint_descriptor *descriptor; const struct libusb_endpoint_descriptor *descriptor;
int endpoint_type; uint32_t endpoint_type;
int transfer_type; uint32_t transfer_type;
uint32_t idx_endpoint;


int FillTransferStructure(libusb_transfer *_transfer, unsigned char *_buffer, Persistent<Function> _callback, uint32_t _timeout, unsigned int num_iso_packets = 0); int FillTransferStructure(libusb_transfer *_transfer, unsigned char *_buffer, Persistent<Function> _callback, uint32_t _timeout, unsigned int num_iso_packets = 0);


Expand All @@ -31,6 +32,7 @@ namespace NodeUsb {
// exposed to V8 // exposed to V8
static Handle<Value> New(const Arguments& args); static Handle<Value> New(const Arguments& args);
static Handle<Value> Write(const Arguments& args); static Handle<Value> Write(const Arguments& args);
static Handle<Value> GetExtraData(const Arguments& args);


}; };


Expand Down
29 changes: 23 additions & 6 deletions src/interface.cc
Expand Up @@ -45,6 +45,7 @@ namespace NodeUsb {
NODE_SET_PROTOTYPE_METHOD(t, "release", Interface::Release); NODE_SET_PROTOTYPE_METHOD(t, "release", Interface::Release);
NODE_SET_PROTOTYPE_METHOD(t, "setAlternateSetting", Interface::AlternateSetting); NODE_SET_PROTOTYPE_METHOD(t, "setAlternateSetting", Interface::AlternateSetting);
NODE_SET_PROTOTYPE_METHOD(t, "isKernelDriverActive", Interface::IsKernelDriverActive); NODE_SET_PROTOTYPE_METHOD(t, "isKernelDriverActive", Interface::IsKernelDriverActive);
NODE_SET_PROTOTYPE_METHOD(t, "getExtraData", Interface::GetExtraData);


// Make it visible in JavaScript // Make it visible in JavaScript
target->Set(String::NewSymbol("Interface"), t->GetFunction()); target->Set(String::NewSymbol("Interface"), t->GetFunction());
Expand Down Expand Up @@ -78,7 +79,7 @@ namespace NodeUsb {
interface->Wrap(args.This()); interface->Wrap(args.This());


#define LIBUSB_INTERFACE_DESCRIPTOR_STRUCT_TO_V8(name) \ #define LIBUSB_INTERFACE_DESCRIPTOR_STRUCT_TO_V8(name) \
args.This()->Set(V8STR(#name), Integer::New(interface->descriptor->name)); args.This()->Set(V8STR(#name), Uint32::New(interface->descriptor->name));
LIBUSB_INTERFACE_DESCRIPTOR_STRUCT_TO_V8(bLength) LIBUSB_INTERFACE_DESCRIPTOR_STRUCT_TO_V8(bLength)
LIBUSB_INTERFACE_DESCRIPTOR_STRUCT_TO_V8(bDescriptorType) LIBUSB_INTERFACE_DESCRIPTOR_STRUCT_TO_V8(bDescriptorType)
LIBUSB_INTERFACE_DESCRIPTOR_STRUCT_TO_V8(bInterfaceNumber) LIBUSB_INTERFACE_DESCRIPTOR_STRUCT_TO_V8(bInterfaceNumber)
Expand Down Expand Up @@ -106,6 +107,22 @@ namespace NodeUsb {
return scope.Close(Uint32::New(self->idx_alt_setting)); return scope.Close(Uint32::New(self->idx_alt_setting));
} }


Handle<Value> Interface::GetExtraData(const Arguments& args) {
LOCAL(Interface, self, args.This())

int m = (*self->descriptor).extra_length;

Local<Array> r = Array::New(m);

for (int i = 0; i < m; i++) {
uint32_t c = (*self->descriptor).extra[i];

r->Set(i, Uint32::New(c));
}

return scope.Close(r);
}

Handle<Value> Interface::IsKernelDriverActive(const Arguments& args) { Handle<Value> Interface::IsKernelDriverActive(const Arguments& args) {
LOCAL(Interface, self, args.This()) LOCAL(Interface, self, args.This())
OPEN_DEVICE_HANDLE_NEEDED(scope) OPEN_DEVICE_HANDLE_NEEDED(scope)
Expand Down Expand Up @@ -265,14 +282,14 @@ namespace NodeUsb {
int numEndpoints = (*self->descriptor).bNumEndpoints; int numEndpoints = (*self->descriptor).bNumEndpoints;


for (int i = 0; i < numEndpoints; i++) { for (int i = 0; i < numEndpoints; i++) {
libusb_endpoint_descriptor ep = (*self->descriptor).endpoint[i]; Local<Value> args_new_endpoint[4] = {

Local<Value> args_new_endpoint[2] = {
External::New(self->device_container), External::New(self->device_container),
External::New(&ep), Uint32::New(self->idx_interface),
Uint32::New(self->idx_alt_setting),
Uint32::New(i)
}; };
// create new object instance of class NodeUsb::Endpoint // create new object instance of class NodeUsb::Endpoint
Persistent<Object> js_endpoint(Endpoint::constructor_template->GetFunction()->NewInstance(2, args_new_endpoint)); Persistent<Object> js_endpoint(Endpoint::constructor_template->GetFunction()->NewInstance(4, args_new_endpoint));
r->Set(i, js_endpoint); r->Set(i, js_endpoint);
} }


Expand Down
1 change: 1 addition & 0 deletions src/interface.h
Expand Up @@ -28,6 +28,7 @@ namespace NodeUsb {
static Handle<Value> DetachKernelDriver(const Arguments& args); static Handle<Value> DetachKernelDriver(const Arguments& args);
static Handle<Value> AttachKernelDriver(const Arguments& args); static Handle<Value> AttachKernelDriver(const Arguments& args);
static Handle<Value> Claim(const Arguments& args); static Handle<Value> Claim(const Arguments& args);
static Handle<Value> GetExtraData(const Arguments& args);
static Handle<Value> GetEndpoints(const Arguments& args); static Handle<Value> GetEndpoints(const Arguments& args);


struct release_request:device_request { struct release_request:device_request {
Expand Down
10 changes: 9 additions & 1 deletion tests/node-usb-test.js
Expand Up @@ -21,6 +21,11 @@ var devices = instance.get_devices();
assert.notEqual(devices, undefined, "getDevices() must not be undefined"); assert.notEqual(devices, undefined, "getDevices() must not be undefined");
assert.ok((devices.length > 0), "getDevices() must be larger than 0 (assume that at least one host controller is available)"); assert.ok((devices.length > 0), "getDevices() must be larger than 0 (assume that at least one host controller is available)");


function assert_extra_length(obj) {
var r = obj.getExtraData();
assert.ok((r.length == obj.extra_length), "getExtraLength() (length is: " + r.length + ") + must be equal to .extra_length (is: " + obj.extra_length + ")");
}

for (var i = 0; i < devices.length; i++) { for (var i = 0; i < devices.length; i++) {
var device = devices[i]; var device = devices[i];
var deviceDesc = undefined; var deviceDesc = undefined;
Expand All @@ -43,6 +48,7 @@ for (var i = 0; i < devices.length; i++) {
} }
} }
assert.ok(found, "could not find USB interface with find_by_vid_and_pid with equal busNumber and deviceAddress"); assert.ok(found, "could not find USB interface with find_by_vid_and_pid with equal busNumber and deviceAddress");
assert_extra_length(device);


var interfaces = device.getInterfaces(); var interfaces = device.getInterfaces();


Expand All @@ -51,13 +57,15 @@ for (var i = 0; i < devices.length; i++) {


for (var j = 0; j < interfaces.length; j++) { for (var j = 0; j < interfaces.length; j++) {
var interface = interfaces[j]; var interface = interfaces[j];
assert_extra_length(interface);

var endpoints = interface.getEndpoints(); var endpoints = interface.getEndpoints();
assert.ok((endpoints != undefined), "Device.getEndpoints() must return an array"); assert.ok((endpoints != undefined), "Device.getEndpoints() must return an array");
assert.ok((endpoints.length >= 0), "Device.getEndpoints() must return an array with length >= 0"); assert.ok((endpoints.length >= 0), "Device.getEndpoints() must return an array with length >= 0");


for (k = 0; k < endpoints.length; k++) { for (k = 0; k < endpoints.length; k++) {
var endpoint = endpoints[k]; var endpoint = endpoints[k];
// console.log(endpoint); assert_extra_length(endpoint);
} }
} }


Expand Down
6 changes: 6 additions & 0 deletions usb.js
Expand Up @@ -11,6 +11,12 @@ exports.create = function() {
usbInstance.get_devices = function() { usbInstance.get_devices = function() {
if (devices == undefined) { if (devices == undefined) {
devices = this.getDevices(); devices = this.getDevices();

for (var i = 0, m = devices.length; i < m; i++) {
var device = devices[i];
var dd = device.getConfigDescriptor();
device.extra_length = dd.extra_length;
}
} }


return devices; return devices;
Expand Down

0 comments on commit 71bca45

Please sign in to comment.