Skip to content

Commit

Permalink
Tells coprocessor to disable USB channel before claiming interface
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnyman727 committed Dec 11, 2015
1 parent 0ad3070 commit 1c20247
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 28 deletions.
75 changes: 47 additions & 28 deletions lib/usb_connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,39 +119,58 @@ USB.Connection.prototype.open = function() {
return reject(e, self);
}
// Set interface settings
self.intf.setAltSetting(2, function(error) {
if (error) {
return reject(error, self);
}
self.epIn = self.intf.endpoints[0];
self.epOut = self.intf.endpoints[1];
if (!self.epIn || !self.epOut) {
return reject(new Error('Device endpoints were not able to be loaded'), self);
}

// Map desciptions
self.device.getStringDescriptor(self.device.deviceDescriptor.iSerialNumber, function(error, data) {
if (error) {
return reject(error, self);
return self.setAltSetting()
.then(() => {
self.epIn = self.intf.endpoints[0];
self.epOut = self.intf.endpoints[1];
if (!self.epIn || !self.epOut) {
return reject(new Error('Device endpoints were not able to be loaded'), self);
}

self.serialNumber = data;
// Register this connection with daemon (keeps track of active remote processes)
Daemon.register(self);
// Map desciptions
self.device.getStringDescriptor(self.device.deviceDescriptor.iSerialNumber, function(error, data) {
if (error) {
return reject(error, self);
}

// If the USB Pipe isn't enabled on the other end (ie it is booting)
self.epIn.on('error', function(err) {
// Close the device resources
self._close();
// Catch the error and return if we haven't already
return reject(err);
self.serialNumber = data;
// Register this connection with daemon (keeps track of active remote processes)
Daemon.register(self);

// If the USB Pipe isn't enabled on the other end (ie it is booting)
self.epIn.on('error', function(err) {
// Close the device resources
self._close();
// Catch the error and return if we haven't already
return reject(err);
});

// Start receiving messages
self._receiveMessages();
// If all is well, resolve the promise with the valid connection
return resolve(self);
});
})
.catch(reject);
});
};

// Start receiving messages
self._receiveMessages();
// If all is well, resolve the promise with the valid connection
return resolve(self);
});
USB.Connection.prototype.setAltSetting = function() {
return new Promise((resolve, reject) => {
// Set interface settings
this.intf.setAltSetting(0, (error) => {
if (error) {
return reject(error, this);
} else {
// Set interface settings
this.intf.setAltSetting(2, (error) => {
if (error) {
return reject(error, this);
} else {
return resolve();
}
});
}
});
});
};
Expand Down
95 changes: 95 additions & 0 deletions test/unit/usb_connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,101 @@ exports['USB.Connection.prototype._write'] = {
},
};

exports['USB.Connection.prototype.open'] = {
setUp: function(done) {
var self = this;
this.sandbox = sinon.sandbox.create();
this.err = this.sandbox.stub(logs, 'err');
this.processExit = this.sandbox.stub(process, 'exit');
this.usbConnection = new USB.Connection({});
this.usbConnection.epOut = new Emitter();
this.usbConnection.epOut.transfer = this.sandbox.spy();
this.usbConnection.epIn = new Emitter();
this.usbConnection.epIn.startPoll = this.sandbox.spy();
this.closeFunc = this.sandbox.spy(this.usbConnection, '_close');
this.fakeInterface = {
claim: function() {},
setAltSetting: function(arg1, cb) {
cb();
},
endpoints: [self.usbConnection.epIn, self.usbConnection.epOut],
};
this.sandbox.stub(this.usbConnection, 'device', {
open: function() {},
interface: function() {
return self.fakeInterface;
},
getStringDescriptor: function(arg1, cb) {
cb();
},
deviceDescriptor: {
iSerialNumber: 'blah',
}
});
this.openDevice = this.sandbox.spy(this.usbConnection.device, 'open');
this.interface = this.sandbox.spy(this.usbConnection.device, 'interface');
this.claim = this.sandbox.spy(this.fakeInterface, 'claim');
this.setAltSetting = this.sandbox.spy(this.fakeInterface, 'setAltSetting');
this.getStringDescriptor = this.sandbox.spy(this.usbConnection.device, 'getStringDescriptor');
this.daemonRegister = this.sandbox.spy(Daemon, 'register');
done();
},

tearDown: function(done) {
this.sandbox.restore();
done();
},

standardOpen: function(test) {
test.expect(11);

this.usbConnection.open()
.then(() => {
test.ok(this.openDevice.calledOnce);
test.ok(this.interface.calledOnce);
test.ok(this.interface.alwaysCalledWith(0));
test.ok(this.claim.calledOnce);
test.ok(this.setAltSetting.calledTwice);
test.equal(this.setAltSetting.firstCall.args[0], 0);
test.equal(this.setAltSetting.secondCall.args[0], 2);
test.ok(this.getStringDescriptor.calledOnce);
test.ok(this.daemonRegister.calledOnce);
test.equal(this.closeFunc.called, false);
test.ok(this.usbConnection.epIn.startPoll.calledOnce);
test.done();
})
.catch(function() {
// It should not error
test.fail();
});
},

setAltSettingFails: function(test) {
test.expect(9);

this.connectionAltSetting = this.sandbox.stub(this.usbConnection, 'setAltSetting').returns(Promise.reject('bad usb things'));

this.usbConnection.open()
.then(() => {
// It should not succeed
test.fail();
})
.catch((err) => {
test.ok(err);
test.ok(this.openDevice.calledOnce);
test.equal(this.interface.called, true);
test.equal(this.claim.called, true);
test.equal(this.setAltSetting.called, false);
test.equal(this.getStringDescriptor.called, false);
test.equal(this.daemonRegister.called, false);
test.equal(this.closeFunc.called, false);
test.equal(this.usbConnection.epIn.startPoll.called, false);
test.done();
});
},

};

exports['USB.Connection.prototype._receiveMessages'] = {
setUp: function(done) {
this.sandbox = sinon.sandbox.create();
Expand Down

0 comments on commit 1c20247

Please sign in to comment.