Skip to content
This repository was archived by the owner on Jul 31, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"esversion": 6,
"undef": true,
"node": true
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ process.env['BLENO_DEVICE_NAME'] = 'custom device name';

bleno uses a 100 ms advertising interval by default.

A custom advertising interval can be specified by setting the ```BLENO_ADVERTISING_INTERVAL``` enviroment variable with the desired value in milliseconds:
A custom advertising interval can be specified by setting the ```BLENO_ADVERTISING_INTERVAL``` environment variable with the desired value in milliseconds:

```sh
sudo BLENO_ADVERTISING_INTERVAL=500 node <your file>.js
Expand Down
42 changes: 25 additions & 17 deletions lib/hci-socket/hci.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,11 @@ Hci.prototype.init = function() {
};

Hci.prototype.resetBuffers = function() {
this._mainHandle = null;
this._handleAclsInProgress = {};
this._handleBuffers = {};
this._aclOutQueue = [];
}
};

Hci.prototype.pollIsDevUp = function() {
var isDevUp = this._socket.isDevUp();
Expand Down Expand Up @@ -146,7 +147,7 @@ Hci.prototype.initDev = function() {
this.readLeHostSupported();
this.readBdAddr();
this.leReadBufferSize();
}
};

Hci.prototype.setSocketFilter = function() {
var filter = new Buffer(14);
Expand Down Expand Up @@ -467,14 +468,14 @@ Hci.prototype.pushAclOutQueue = function() {
debug("\tin progress = " + inProgress);
debug("\twaiting = " + this._aclOutQueue.length);
}
}
};

Hci.prototype.writeOneAclDataPkt = function() {
var pkt = this._aclOutQueue.shift();
this._handleAclsInProgress[pkt.handle]++;
debug('write acl data pkt frag ' + pkt.fragId + ' handle ' + pkt.handle + ' - writing: ' + pkt.pkt.toString('hex'));
this._socket.write(pkt.pkt);
}
};

Hci.prototype.onSocketData = function(data) {
debug('onSocketData: ' + data.toString('hex'));
Expand All @@ -491,9 +492,14 @@ Hci.prototype.onSocketData = function(data) {

if (subEventType === EVT_DISCONN_COMPLETE) {
handle = data.readUInt16LE(4);
var reason = data.readUInt8(6);

debug('\t\thandle = ' + handle);
if (handle !== this._mainHandle) {
debug('\tignoring event because handle is unknown to bleno.');
debug('\This might be OK in a multi role scenario in which the handle is part of a noble connection.');
return;
}

var reason = data.readUInt8(6);
debug('\t\treason = ' + reason);

/* As per Bluetooth Core specs:
Expand All @@ -503,6 +509,7 @@ Hci.prototype.onSocketData = function(data) {
Controller for the returned Handle have been flushed, and that the
corresponding data buffers have been freed. */
delete this._handleAclsInProgress[handle];
this._mainHandle = null;
var aclOutQueue = [];
var discarded = 0;
for (var i in this._aclOutQueue) {
Expand Down Expand Up @@ -550,22 +557,22 @@ Hci.prototype.onSocketData = function(data) {
this.processLeMetaEvent(leMetaEventType, leMetaEventStatus, leMetaEventData);
} else if (subEventType === EVT_NUMBER_OF_COMPLETED_PACKETS) {
var handles = data.readUInt8(3);
for (var i = 0; i < handles; i++) {
var handle = data.readUInt16LE(4 + i * 4);
var pkts = data.readUInt16LE(6 + i * 4);
debug("\thandle = " + handle);
for (var j = 0; j < handles; j++) {
var handle_ = data.readUInt16LE(4 + j * 4);
var pkts = data.readUInt16LE(6 + j * 4);
debug("\thandle = " + handle_);
debug("\t\tcompleted = " + pkts);
if (this._handleAclsInProgress[handle] === undefined) {
if (this._handleAclsInProgress[handle_] === undefined) {
debug("\t\talready closed");
continue;
}
if (pkts > this._handleAclsInProgress[handle]) {
if (pkts > this._handleAclsInProgress[handle_]) {
// Linux kernel may send acl packets by itself, so be ready for underflow
this._handleAclsInProgress[handle] = 0;
this._handleAclsInProgress[handle_] = 0;
} else {
this._handleAclsInProgress[handle] -= pkts;
this._handleAclsInProgress[handle_] -= pkts;
}
debug("\t\tin progress = " + this._handleAclsInProgress[handle]);
debug("\t\tin progress = " + this._handleAclsInProgress[handle_]);
}
this.pushAclOutQueue();
}
Expand Down Expand Up @@ -615,7 +622,7 @@ Hci.prototype.onSocketData = function(data) {
Hci.prototype.onSocketError = function(error) {
debug('onSocketError: ' + error.message);

if (error.message === 'Operation not permitted') {
if (error.code === 'EPERM') {
this.emit('stateChange', 'unauthorized');
} else if (error.message === 'Network is down') {
// no-op
Expand Down Expand Up @@ -712,7 +719,7 @@ Hci.prototype.processLeReadBufferSize = function(result) {
this._aclMtu = aclMtu;
this._aclMaxInProgress = aclMaxInProgress;
}
}
};

Hci.prototype.processLeMetaEvent = function(eventType, status, data) {
if (eventType === EVT_LE_CONN_COMPLETE) {
Expand Down Expand Up @@ -741,6 +748,7 @@ Hci.prototype.processLeConnComplete = function(status, data) {
debug('\t\t\tsupervision timeout = ' + supervisionTimeout);
debug('\t\t\tmaster clock accuracy = ' + masterClockAccuracy);

this._mainHandle = handle;
this._handleAclsInProgress[handle] = 0;

this.emit('leConnComplete', status, handle, role, addressType, address, interval, latency, supervisionTimeout, masterClockAccuracy);
Expand Down
Loading