diff --git a/.gitignore b/.gitignore index badfaa1..91f36c0 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ lib/binding/ # Dependency directory # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git node_modules + +# VScode +.vscode \ No newline at end of file diff --git a/examples/list-devices-test.js b/examples/list-devices-test.js new file mode 100644 index 0000000..fe0c69c --- /dev/null +++ b/examples/list-devices-test.js @@ -0,0 +1,9 @@ +var UsbBluetoothHciSocket = require('../lib/usb'); +var usbBluetoothHciSocket = new UsbBluetoothHciSocket(); +var usbDevices = usbBluetoothHciSocket.getDeviceList(); +console.log("usbDevices: ", usbDevices); + +var NativeBluetoothHciSocket = require('../lib/native'); +var nativeBluetoothHciSocket = new NativeBluetoothHciSocket(); +var nativeDevices = nativeBluetoothHciSocket.getDeviceList(); +console.log("nativeDevices: ", nativeDevices); \ No newline at end of file diff --git a/lib/usb.js b/lib/usb.js index 8fda700..1027b36 100644 --- a/lib/usb.js +++ b/lib/usb.js @@ -11,6 +11,21 @@ var HCI_EVENT_PKT = 0x04; var OGF_HOST_CTL = 0x03; var OCF_RESET = 0x0003; +var VENDOR_DEVICE_LIST = [ + {vid: 0x0CF3, pid: 0xE300 }, // Qualcomm Atheros QCA61x4 + {vid: 0x0a5c, pid: 0x21e8 }, // Broadcom BCM20702A0 + {vid: 0x19ff, pid: 0x0239 }, // Broadcom BCM20702A0 + {vid: 0x0a12, pid: 0x0001 }, // CSR + {vid: 0x0b05, pid: 0x17cb }, // ASUS BT400 + {vid: 0x8087, pid: 0x07da }, // Intel 6235 + {vid: 0x8087, pid: 0x07dc }, // Intel 7260 + {vid: 0x8087, pid: 0x0a2a }, // Intel 7265 + {vid: 0x8087, pid: 0x0a2b }, // Intel 8265 + {vid: 0x0489, pid: 0xe07a }, // Broadcom BCM20702A1 + {vid: 0x0a5c, pid: 0x6412 }, // Broadcom BCM2045A0 + {vid: 0x050D, pid: 0x065A }, // Belkin BCM20702A0 +]; + function BluetoothHciSocket() { this._isUp = false; @@ -63,19 +78,9 @@ BluetoothHciSocket.prototype.bindUser = function(devId) { this._usbDevice = usb.findByIds(usbVid, usbPid); } } else { - this._usbDevice = - usb.findByIds(0x0CF3,0xE300) || // Qualcomm Atheros QCA61x4 - usb.findByIds(0x0a5c, 0x21e8) || // Broadcom BCM20702A0 - usb.findByIds(0x19ff, 0x0239) || // Broadcom BCM20702A0 - usb.findByIds(0x0a12, 0x0001) || // CSR - usb.findByIds(0x0b05, 0x17cb) || // ASUS BT400 - usb.findByIds(0x8087, 0x07da) || // Intel 6235 - usb.findByIds(0x8087, 0x07dc) || // Intel 7260 - usb.findByIds(0x8087, 0x0a2a) || // Intel 7265 - usb.findByIds(0x8087, 0x0a2b) || // Intel 8265 - usb.findByIds(0x0489, 0xe07a) || // Broadcom BCM20702A1 - usb.findByIds(0x0a5c, 0x6412) || // Broadcom BCM2045A0 - usb.findByIds(0x050D, 0x065A); // Belkin BCM20702A0 + this._usbDevice = VENDOR_DEVICE_LIST + .map(d => usb.findByIds(d.vid, d.pid)) + .find(d => d != null); } if (!this._usbDevice) { @@ -94,6 +99,23 @@ BluetoothHciSocket.prototype.bindUser = function(devId) { this._usbDeviceInterface.claim(); }; +BluetoothHciSocket.prototype.getDeviceList = function() { + return usb.getDeviceList() + .filter(dev => { + return VENDOR_DEVICE_LIST.findIndex(d => { + return dev.deviceDescriptor.idVendor == d.vid && dev.deviceDescriptor.idProduct == d.pid; + }) !== -1; + }) + .map(dev => ({ + "devId": null, + "devUp": null, + "idVendor": dev.deviceDescriptor.idVendor, + "idProduct": dev.deviceDescriptor.idProduct, + "busNumber": dev.busNumber, + "deviceAddress": dev.deviceAddress, + })); +} + BluetoothHciSocket.prototype.bindControl = function() { this._mode = 'control'; }; diff --git a/package.json b/package.json index c129475..43ee21f 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,6 @@ "version": "0.5.2", "description": "Bluetooth HCI socket binding for Node.js", "main": "index.js", - "scripts": { - "test": "jshint lib/*.js" - }, "repository": { "type": "git", "url": "https://github.com/sandeepmistry/node-bluetooth-hci-socket.git" @@ -41,7 +38,8 @@ }, "scripts": { "preinstall": "npm install node-pre-gyp", - "install": "node-pre-gyp install --fallback-to-build" + "install": "node-pre-gyp install --fallback-to-build", + "test": "jshint lib/*.js" }, "binary": { "module_name": "binding", diff --git a/src/BluetoothHciSocket.cpp b/src/BluetoothHciSocket.cpp index 3d5182a..469cda2 100644 --- a/src/BluetoothHciSocket.cpp +++ b/src/BluetoothHciSocket.cpp @@ -121,6 +121,7 @@ NAN_MODULE_INIT(BluetoothHciSocket::Init) { Nan::SetPrototypeMethod(tmpl, "bindUser", BindUser); Nan::SetPrototypeMethod(tmpl, "bindControl", BindControl); Nan::SetPrototypeMethod(tmpl, "isDevUp", IsDevUp); + Nan::SetPrototypeMethod(tmpl, "getDeviceList", GetDeviceList); Nan::SetPrototypeMethod(tmpl, "setFilter", SetFilter); Nan::SetPrototypeMethod(tmpl, "stop", Stop); Nan::SetPrototypeMethod(tmpl, "write", Write); @@ -445,6 +446,44 @@ NAN_METHOD(BluetoothHciSocket::IsDevUp) { info.GetReturnValue().Set(isDevUp); } +NAN_METHOD(BluetoothHciSocket::GetDeviceList) { + Nan::HandleScope scope; + + BluetoothHciSocket* p = node::ObjectWrap::Unwrap(info.This()); + + struct hci_dev_list_req *dl; + struct hci_dev_req *dr; + + dl = (hci_dev_list_req*)calloc(HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl), 1); + dr = dl->dev_req; + + dl->dev_num = HCI_MAX_DEV; + + Local deviceList = Nan::New(); + + if (ioctl(p->_socket, HCIGETDEVLIST, dl) > -1) { + int di = 0; + for (int i = 0; i < dl->dev_num; i++, dr++) { + uint16_t devId = dr->dev_id; + bool devUp = dr->dev_opt & (1 << HCI_UP); + if (dr != NULL) { + v8::Local obj = Nan::New(); + obj->Set(Nan::New("devId").ToLocalChecked(), Nan::New(devId)); + obj->Set(Nan::New("devUp").ToLocalChecked(), Nan::New(devUp)); + obj->Set(Nan::New("idVendor").ToLocalChecked(), Nan::Null()); + obj->Set(Nan::New("idProduct").ToLocalChecked(), Nan::Null()); + obj->Set(Nan::New("busNumber").ToLocalChecked(), Nan::Null()); + obj->Set(Nan::New("deviceAddress").ToLocalChecked(), Nan::Null()); + Nan::Set(deviceList, di++, obj); + } + } + } + + free(dl); + + info.GetReturnValue().Set(deviceList); +} + NAN_METHOD(BluetoothHciSocket::SetFilter) { Nan::HandleScope scope; diff --git a/src/BluetoothHciSocket.h b/src/BluetoothHciSocket.h index 3a4617b..97e4244 100644 --- a/src/BluetoothHciSocket.h +++ b/src/BluetoothHciSocket.h @@ -17,6 +17,7 @@ class BluetoothHciSocket : public node::ObjectWrap { static NAN_METHOD(BindUser); static NAN_METHOD(BindControl); static NAN_METHOD(IsDevUp); + static NAN_METHOD(GetDeviceList); static NAN_METHOD(SetFilter); static NAN_METHOD(Start); static NAN_METHOD(Stop);