@stoprocent/noble 1.19.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +393 -650
- package/examples/advertisement-discovery.js +57 -48
- package/examples/connect-address.js +59 -34
- package/examples/echo.js +59 -69
- package/examples/enter-exit.js +55 -49
- package/examples/multiple-bindings.js +53 -0
- package/examples/peripheral-explorer-async.js +39 -21
- package/examples/peripheral-explorer.ts +52 -0
- package/index.d.ts +249 -209
- package/index.js +4 -1
- package/jest.config.js +4 -0
- package/lib/characteristic.js +153 -127
- package/lib/{win/src/callbacks.h → common/include/Emit.h} +17 -14
- package/lib/common/include/Peripheral.h +31 -0
- package/lib/common/include/ThreadSafeCallback.h +95 -0
- package/lib/{win/src/callbacks.cc → common/src/Emit.cc} +111 -68
- package/lib/descriptor.js +57 -54
- package/lib/hci-socket/acl-stream.js +2 -4
- package/lib/hci-socket/bindings.js +96 -73
- package/lib/hci-socket/gap.js +2 -3
- package/lib/hci-socket/gatt.js +2 -5
- package/lib/hci-socket/hci.js +19 -7
- package/lib/hci-socket/signaling.js +2 -3
- package/lib/hci-socket/smp.js +2 -3
- package/lib/hci-socket/vs.js +1 -0
- package/lib/mac/binding.gyp +5 -7
- package/lib/mac/bindings.js +1 -3
- package/lib/mac/src/ble_manager.h +1 -8
- package/lib/mac/src/ble_manager.mm +87 -44
- package/lib/mac/src/napi_objc.h +1 -0
- package/lib/mac/src/napi_objc.mm +0 -6
- package/lib/mac/src/noble_mac.h +5 -3
- package/lib/mac/src/noble_mac.mm +99 -57
- package/lib/mac/src/objc_cpp.h +3 -2
- package/lib/mac/src/objc_cpp.mm +0 -6
- package/lib/noble.js +579 -488
- package/lib/peripheral.js +171 -174
- package/lib/resolve-bindings.js +37 -30
- package/lib/service.js +58 -55
- package/lib/win/binding.gyp +4 -11
- package/lib/win/bindings.js +1 -3
- package/lib/win/src/ble_manager.cc +291 -166
- package/lib/win/src/ble_manager.h +11 -13
- package/lib/win/src/napi_winrt.cc +1 -7
- package/lib/win/src/napi_winrt.h +1 -1
- package/lib/win/src/noble_winrt.cc +88 -61
- package/lib/win/src/noble_winrt.h +5 -3
- package/lib/win/src/notify_map.cc +0 -7
- package/lib/win/src/notify_map.h +1 -8
- package/lib/win/src/peripheral_winrt.cc +29 -11
- package/lib/win/src/peripheral_winrt.h +1 -1
- package/lib/win/src/radio_watcher.cc +79 -69
- package/lib/win/src/radio_watcher.h +30 -11
- package/lib/win/src/winrt_cpp.cc +1 -1
- package/lib/win/src/winrt_cpp.h +3 -0
- package/package.json +14 -17
- package/prebuilds/darwin-x64+arm64/@stoprocent+noble.node +0 -0
- package/prebuilds/win32-ia32/@stoprocent+noble.node +0 -0
- package/prebuilds/win32-x64/@stoprocent+noble.node +0 -0
- package/test/lib/characteristic.test.js +202 -322
- package/test/lib/descriptor.test.js +62 -95
- package/test/lib/hci-socket/acl-stream.test.js +112 -108
- package/test/lib/hci-socket/bindings.test.js +576 -365
- package/test/lib/hci-socket/hci.test.js +442 -473
- package/test/lib/hci-socket/signaling.test.js +45 -48
- package/test/lib/hci-socket/smp.test.js +144 -142
- package/test/lib/hci-socket/vs.test.js +193 -18
- package/test/lib/peripheral.test.js +492 -322
- package/test/lib/resolve-bindings.test.js +207 -82
- package/test/lib/service.test.js +79 -88
- package/test/noble.test.js +381 -1085
- package/.editorconfig +0 -11
- package/.nycrc.json +0 -4
- package/codecov.yml +0 -5
- package/examples/cache-gatt-discovery.js +0 -198
- package/examples/cache-gatt-reconnect.js +0 -164
- package/examples/ext-advertisement-discovery.js +0 -65
- package/examples/peripheral-explorer.js +0 -225
- package/examples/pizza/central.js +0 -194
- package/examples/pizza/pizza.js +0 -60
- package/examples/test/test.custom.js +0 -131
- package/examples/uart-bind-params.js +0 -28
- package/lib/distributed/bindings.js +0 -326
- package/lib/mac/src/callbacks.cc +0 -222
- package/lib/mac/src/callbacks.h +0 -84
- package/lib/mac/src/peripheral.h +0 -23
- package/lib/resolve-bindings-web.js +0 -9
- package/lib/webbluetooth/bindings.js +0 -368
- package/lib/websocket/bindings.js +0 -321
- package/lib/win/src/peripheral.h +0 -23
- package/test/lib/distributed/bindings.test.js +0 -918
- package/test/lib/webbluetooth/bindings.test.js +0 -190
- package/test/lib/websocket/bindings.test.js +0 -456
- package/test/mocha.setup.js +0 -0
- package/with-bindings.js +0 -5
- package/with-custom-binding.js +0 -6
- package/ws-slave.js +0 -404
|
@@ -6,25 +6,33 @@ const { assert } = sinon;
|
|
|
6
6
|
|
|
7
7
|
describe('hci-socket hci', () => {
|
|
8
8
|
const deviceId = 'deviceId';
|
|
9
|
-
const
|
|
9
|
+
const mockSocket = sinon.stub();
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
// Mock the crypto module
|
|
12
|
+
jest.mock('os', () => ({
|
|
13
|
+
platform: () => 'linux',
|
|
14
|
+
release: () => '5.10.0-11-amd64'
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
jest.mock('@stoprocent/bluetooth-hci-socket', () => ({
|
|
18
|
+
loadDriver: () => mockSocket
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
const Hci = require('../../../lib/hci-socket/hci');
|
|
14
22
|
|
|
15
23
|
let hci;
|
|
16
24
|
|
|
17
25
|
beforeEach(() => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
mockSocket.prototype.on = sinon.stub();
|
|
27
|
+
mockSocket.prototype.bindUser = sinon.stub();
|
|
28
|
+
mockSocket.prototype.bindRaw = sinon.stub();
|
|
29
|
+
mockSocket.prototype.start = sinon.stub();
|
|
30
|
+
mockSocket.prototype.isDevUp = sinon.stub();
|
|
31
|
+
mockSocket.prototype.removeAllListeners = sinon.stub();
|
|
32
|
+
mockSocket.prototype.setFilter = sinon.stub();
|
|
33
|
+
mockSocket.prototype.setAddress = sinon.stub();
|
|
34
|
+
mockSocket.prototype.write = sinon.stub();
|
|
35
|
+
|
|
28
36
|
hci = new Hci({});
|
|
29
37
|
hci._deviceId = deviceId;
|
|
30
38
|
});
|
|
@@ -567,6 +575,7 @@ describe('hci-socket hci', () => {
|
|
|
567
575
|
});
|
|
568
576
|
|
|
569
577
|
describe('onSocketData', () => {
|
|
578
|
+
// Define the standard ACL queue used in tests
|
|
570
579
|
const aclQueue = [
|
|
571
580
|
{
|
|
572
581
|
handle: 4660,
|
|
@@ -581,573 +590,526 @@ describe('hci-socket hci', () => {
|
|
|
581
590
|
packet: Buffer.from([0x02])
|
|
582
591
|
}
|
|
583
592
|
];
|
|
584
|
-
|
|
593
|
+
|
|
594
|
+
// Event callback mocks
|
|
585
595
|
let disconnCompleteCallback;
|
|
586
596
|
let encryptChangeCallback;
|
|
587
597
|
let aclDataPktCallback;
|
|
588
598
|
let leScanEnableSetCmdCallback;
|
|
589
|
-
|
|
599
|
+
|
|
590
600
|
beforeEach(() => {
|
|
591
|
-
|
|
592
|
-
hci
|
|
593
|
-
hci
|
|
594
|
-
hci
|
|
595
|
-
|
|
601
|
+
// Setup spies on HCI methods - preserve actual implementation
|
|
602
|
+
jest.spyOn(hci, 'flushAcl');
|
|
603
|
+
jest.spyOn(hci, 'processCmdCompleteEvent');
|
|
604
|
+
jest.spyOn(hci, 'processCmdStatusEvent');
|
|
605
|
+
|
|
606
|
+
hci.processLeMetaEvent = jest.fn();
|
|
607
|
+
|
|
608
|
+
// Suppress console.warn
|
|
609
|
+
jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
610
|
+
|
|
611
|
+
// Setup HCI's internal state for testing
|
|
596
612
|
hci._aclQueue = [...aclQueue];
|
|
613
|
+
hci._aclConnections = new Map();
|
|
597
614
|
hci._aclConnections.set(4660, { pending: 3 });
|
|
598
615
|
hci._aclConnections.set(4661, { pending: 2 });
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
616
|
+
hci._handleBuffers = {};
|
|
617
|
+
|
|
618
|
+
// Setup event listener callbacks as mocks
|
|
619
|
+
disconnCompleteCallback = jest.fn();
|
|
620
|
+
encryptChangeCallback = jest.fn();
|
|
621
|
+
aclDataPktCallback = jest.fn();
|
|
622
|
+
leScanEnableSetCmdCallback = jest.fn();
|
|
623
|
+
|
|
624
|
+
// Register event handlers
|
|
604
625
|
hci.on('disconnComplete', disconnCompleteCallback);
|
|
605
626
|
hci.on('encryptChange', encryptChangeCallback);
|
|
606
627
|
hci.on('aclDataPkt', aclDataPktCallback);
|
|
607
628
|
hci.on('leScanEnableSetCmd', leScanEnableSetCmdCallback);
|
|
608
629
|
});
|
|
609
|
-
|
|
630
|
+
|
|
610
631
|
afterEach(() => {
|
|
611
|
-
|
|
632
|
+
// Clear all mocks between tests
|
|
633
|
+
jest.restoreAllMocks();
|
|
612
634
|
});
|
|
613
|
-
|
|
614
|
-
|
|
635
|
+
|
|
636
|
+
test('should flushAcl - HCI_EVENT_PKT / EVT_DISCONN_COMPLETE', () => {
|
|
615
637
|
const eventType = 4;
|
|
616
638
|
const subEventType = 5;
|
|
617
639
|
const data = Buffer.from([eventType, subEventType, 0, 0, 0x34, 0x12, 3]);
|
|
618
|
-
|
|
640
|
+
|
|
619
641
|
hci.onSocketData(data);
|
|
620
|
-
|
|
621
|
-
//
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
//
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
//
|
|
633
|
-
|
|
642
|
+
|
|
643
|
+
// Called
|
|
644
|
+
expect(hci.flushAcl).toHaveBeenCalledTimes(1);
|
|
645
|
+
expect(disconnCompleteCallback).toHaveBeenCalledWith(4660, 3);
|
|
646
|
+
|
|
647
|
+
// Not called
|
|
648
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
649
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
650
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
651
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
652
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
653
|
+
|
|
654
|
+
// HCI state checks
|
|
655
|
+
expect(hci._aclQueue).toEqual([
|
|
634
656
|
{
|
|
635
657
|
handle: 4661,
|
|
636
658
|
packet: Buffer.from([0x02])
|
|
637
659
|
}
|
|
638
660
|
]);
|
|
639
|
-
|
|
640
|
-
|
|
661
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual([4661]);
|
|
662
|
+
expect(hci._aclConnections.get(4661)).toEqual({ pending: 2 });
|
|
641
663
|
});
|
|
642
|
-
|
|
643
|
-
|
|
664
|
+
|
|
665
|
+
test('should only emit encryptChange - HCI_EVENT_PKT / EVT_ENCRYPT_CHANGE', () => {
|
|
644
666
|
const eventType = 4;
|
|
645
667
|
const subEventType = 8;
|
|
646
668
|
const data = Buffer.from([eventType, subEventType, 0, 0, 0x34, 0x12, 3]);
|
|
647
669
|
hci.onSocketData(data);
|
|
648
|
-
|
|
649
|
-
//
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
//
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
//
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
});
|
|
666
|
-
|
|
667
|
-
|
|
670
|
+
|
|
671
|
+
// Called
|
|
672
|
+
expect(encryptChangeCallback).toHaveBeenCalledWith(4660, 3);
|
|
673
|
+
|
|
674
|
+
// Not called
|
|
675
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
676
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
677
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
678
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
679
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
680
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
681
|
+
|
|
682
|
+
// HCI state checks
|
|
683
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
684
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
685
|
+
expect(hci._aclConnections.get(4660)).toEqual({ pending: 3 });
|
|
686
|
+
expect(hci._aclConnections.get(4661)).toEqual({ pending: 2 });
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
test('should only processCmdCompleteEvent - HCI_EVENT_PKT / EVT_CMD_COMPLETE', () => {
|
|
668
690
|
const eventType = 4;
|
|
669
691
|
const subEventType = 14;
|
|
670
692
|
const data = Buffer.from([eventType, subEventType, 0, 0, 0x34, 0x12, 3, 9, 9]);
|
|
671
|
-
hci.onSocketData(data);
|
|
672
|
-
|
|
673
|
-
// called
|
|
674
|
-
assert.calledOnceWithExactly(hci.processCmdCompleteEvent, 4660, 3, Buffer.from([9, 9]));
|
|
675
|
-
|
|
676
|
-
// not called
|
|
677
|
-
assert.notCalled(hci.flushAcl);
|
|
678
|
-
assert.notCalled(encryptChangeCallback);
|
|
679
|
-
assert.notCalled(hci.processLeMetaEvent);
|
|
680
|
-
assert.notCalled(disconnCompleteCallback);
|
|
681
|
-
assert.notCalled(aclDataPktCallback);
|
|
682
|
-
assert.notCalled(leScanEnableSetCmdCallback);
|
|
683
|
-
|
|
684
|
-
// hci checks
|
|
685
|
-
should(hci._aclQueue).deepEqual(aclQueue);
|
|
686
|
-
should(hci._aclConnections).have.keys(4660, 4661);
|
|
687
|
-
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
|
|
688
|
-
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
|
|
689
|
-
|
|
690
|
-
describe('LE_READ_LOCAL_SUPPORTED_FEATURES', () => {
|
|
691
|
-
beforeEach(() => {
|
|
692
|
-
hci.setCodedPhySupport = sinon.spy();
|
|
693
|
-
hci.setEventMask = sinon.spy();
|
|
694
|
-
hci.setLeEventMask = sinon.spy();
|
|
695
|
-
hci.readLocalVersion = sinon.spy();
|
|
696
|
-
hci.writeLeHostSupported = sinon.spy();
|
|
697
|
-
hci.readLeHostSupported = sinon.spy();
|
|
698
|
-
hci.readLeBufferSize = sinon.spy();
|
|
699
|
-
hci.readBdAddr = sinon.spy();
|
|
700
|
-
});
|
|
701
|
-
|
|
702
|
-
it('should not process on error status', () => {
|
|
703
|
-
const cmd = 8195;
|
|
704
|
-
const status = 1;
|
|
705
|
-
const result = Buffer.from([0x00, 0x00, 0x00, 0x00]);
|
|
706
|
-
|
|
707
|
-
hci.processCmdCompleteEvent(cmd, status, result);
|
|
708
|
-
|
|
709
|
-
// Verify no methods were called
|
|
710
|
-
assert.notCalled(hci.setCodedPhySupport);
|
|
711
|
-
assert.notCalled(hci.setEventMask);
|
|
712
|
-
assert.notCalled(hci.setLeEventMask);
|
|
713
|
-
assert.notCalled(hci.readLocalVersion);
|
|
714
|
-
assert.notCalled(hci.writeLeHostSupported);
|
|
715
|
-
assert.notCalled(hci.readLeHostSupported);
|
|
716
|
-
assert.notCalled(hci.readLeBufferSize);
|
|
717
|
-
assert.notCalled(hci.readBdAddr);
|
|
718
693
|
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
should(hci._isExtended).equal(false);
|
|
742
|
-
});
|
|
743
|
-
|
|
744
|
-
it('should process with extended features', () => {
|
|
745
|
-
const cmd = 8195;
|
|
746
|
-
const status = 0;
|
|
747
|
-
const result = Buffer.from("bd5f660000000000", "hex");
|
|
748
|
-
|
|
749
|
-
hci.processCmdCompleteEvent(cmd, status, result);
|
|
750
|
-
|
|
751
|
-
// Verify all methods were called including extended-specific
|
|
752
|
-
assert.calledOnce(hci.setCodedPhySupport);
|
|
753
|
-
assert.calledOnce(hci.setEventMask);
|
|
754
|
-
assert.calledOnce(hci.setLeEventMask);
|
|
755
|
-
assert.calledOnce(hci.readLocalVersion);
|
|
756
|
-
assert.calledOnce(hci.writeLeHostSupported);
|
|
757
|
-
assert.calledOnce(hci.readLeHostSupported);
|
|
758
|
-
assert.calledOnce(hci.readLeBufferSize);
|
|
759
|
-
assert.calledOnce(hci.readBdAddr);
|
|
760
|
-
|
|
761
|
-
should(hci._isExtended).equal(true);
|
|
762
|
-
});
|
|
763
|
-
});
|
|
764
|
-
});
|
|
765
|
-
|
|
766
|
-
it('should only processCmdStatusEvent - HCI_EVENT_PKT / EVT_CMD_STATUS', () => {
|
|
694
|
+
hci.onSocketData(data);
|
|
695
|
+
|
|
696
|
+
// Called
|
|
697
|
+
expect(hci.processCmdCompleteEvent).toHaveBeenCalledWith(4660, 3, Buffer.from([9, 9]));
|
|
698
|
+
|
|
699
|
+
// Not called
|
|
700
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
701
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
702
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
703
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
704
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
705
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
706
|
+
|
|
707
|
+
// HCI state checks
|
|
708
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
709
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
710
|
+
expect(hci._aclConnections.get(4660)).toEqual({ pending: 3 });
|
|
711
|
+
expect(hci._aclConnections.get(4661)).toEqual({ pending: 2 });
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
test('should only processCmdStatusEvent - HCI_EVENT_PKT / EVT_CMD_STATUS', () => {
|
|
767
715
|
const eventType = 4;
|
|
768
716
|
const subEventType = 15;
|
|
769
717
|
const data = Buffer.from([eventType, subEventType, 4, 2, 0x34, 0x12, 3, 9, 9]);
|
|
770
718
|
hci.onSocketData(data);
|
|
771
|
-
|
|
772
|
-
//
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
//
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
//
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
});
|
|
790
|
-
|
|
791
|
-
|
|
719
|
+
|
|
720
|
+
// Called
|
|
721
|
+
expect(hci.processCmdStatusEvent).toHaveBeenCalledWith(786, 2);
|
|
722
|
+
|
|
723
|
+
// Not called
|
|
724
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
725
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
726
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
727
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
728
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
729
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
730
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
731
|
+
|
|
732
|
+
// HCI state checks
|
|
733
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
734
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
735
|
+
expect(hci._aclConnections.get(4660)).toEqual({ pending: 3 });
|
|
736
|
+
expect(hci._aclConnections.get(4661)).toEqual({ pending: 2 });
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
test('should only processLeMetaEvent - HCI_EVENT_PKT / EVT_LE_META_EVENT', () => {
|
|
792
740
|
const eventType = 4;
|
|
793
741
|
const subEventType = 62;
|
|
794
742
|
const data = Buffer.from([eventType, subEventType, 0, 1, 0x34, 0x12, 3, 9, 9]);
|
|
795
|
-
hci.onSocketData(data);
|
|
796
|
-
|
|
797
|
-
// called
|
|
798
|
-
assert.calledOnceWithExactly(hci.processLeMetaEvent, 1, 52, Buffer.from([0x12, 3, 9, 9]));
|
|
799
743
|
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
744
|
+
hci.onSocketData(data);
|
|
745
|
+
|
|
746
|
+
// Called
|
|
747
|
+
expect(hci.processLeMetaEvent).toHaveBeenCalledWith(1, 52, Buffer.from([0x12, 3, 9, 9]));
|
|
748
|
+
|
|
749
|
+
// Not called
|
|
750
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
751
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
752
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
753
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
754
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
755
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
756
|
+
|
|
757
|
+
// HCI state checks
|
|
758
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
759
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
760
|
+
expect(hci._aclConnections.get(4660)).toEqual({ pending: 3 });
|
|
761
|
+
expect(hci._aclConnections.get(4661)).toEqual({ pending: 2 });
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
test('should only flushAcl - HCI_EVENT_PKT / EVT_NUMBER_OF_COMPLETED_PACKETS', () => {
|
|
816
765
|
const eventType = 4;
|
|
817
766
|
const subEventType = 19;
|
|
818
767
|
const data = Buffer.from([eventType, subEventType, 0, 1, 0x34, 0x12, 3, 9, 9]);
|
|
819
768
|
hci.onSocketData(data);
|
|
820
|
-
|
|
821
|
-
//
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
//
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
//
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
});
|
|
838
|
-
|
|
839
|
-
|
|
769
|
+
|
|
770
|
+
// Called
|
|
771
|
+
expect(hci.flushAcl).toHaveBeenCalled();
|
|
772
|
+
|
|
773
|
+
// Not called
|
|
774
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
775
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
776
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
777
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
778
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
779
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
780
|
+
|
|
781
|
+
// HCI state checks
|
|
782
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
783
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
784
|
+
expect(hci._aclConnections.get(4660)).toEqual({ pending: 0 });
|
|
785
|
+
expect(hci._aclConnections.get(4661)).toEqual({ pending: 2 });
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
test('should do nothing - HCI_EVENT_PKT / unknown subEventType', () => {
|
|
840
789
|
const eventType = 4;
|
|
841
790
|
const subEventType = 122;
|
|
842
791
|
const data = Buffer.from([eventType, subEventType, 0, 1, 0x34, 0x12, 3, 9, 9]);
|
|
843
792
|
hci.onSocketData(data);
|
|
844
|
-
|
|
845
|
-
// called
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
it('should only emit aclDataPkt - HCI_ACLDATA_PKT / ACL_START', () => {
|
|
793
|
+
|
|
794
|
+
// Not called - nothing should happen
|
|
795
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
796
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
797
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
798
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
799
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
800
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
801
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
802
|
+
|
|
803
|
+
// HCI state checks
|
|
804
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
805
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
806
|
+
expect(hci._aclConnections.get(4660)).toEqual({ pending: 3 });
|
|
807
|
+
expect(hci._aclConnections.get(4661)).toEqual({ pending: 2 });
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
test('should only emit aclDataPkt - HCI_ACLDATA_PKT / ACL_START', () => {
|
|
864
811
|
const eventType = 2;
|
|
865
812
|
const subEventTypeP1 = 0xf2;
|
|
866
813
|
const subEventTypeP2 = 0x24;
|
|
867
814
|
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8, 7]);
|
|
868
815
|
hci.onSocketData(data);
|
|
869
|
-
|
|
870
|
-
//
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
//
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
//
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
it('should register handle buffer - HCI_ACLDATA_PKT / ACL_START', () => {
|
|
816
|
+
|
|
817
|
+
// Called
|
|
818
|
+
expect(aclDataPktCallback).toHaveBeenCalledWith(1266, 2307, Buffer.from([9, 8, 7]));
|
|
819
|
+
|
|
820
|
+
// Not called
|
|
821
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
822
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
823
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
824
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
825
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
826
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
827
|
+
|
|
828
|
+
// HCI state checks
|
|
829
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
830
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
831
|
+
expect(hci._aclConnections.get(4660)).toEqual({ pending: 3 });
|
|
832
|
+
expect(hci._aclConnections.get(4661)).toEqual({ pending: 2 });
|
|
833
|
+
expect(hci._handleBuffers).toEqual({});
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
test('should register handle buffer - HCI_ACLDATA_PKT / ACL_START with incomplete data', () => {
|
|
891
837
|
const eventType = 2;
|
|
892
838
|
const subEventTypeP1 = 0xf2;
|
|
893
839
|
const subEventTypeP2 = 0x24;
|
|
894
840
|
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8]);
|
|
895
841
|
hci.onSocketData(data);
|
|
896
|
-
|
|
897
|
-
// called
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
cid: 2307,
|
|
918
|
-
data: Buffer.from([9, 8])
|
|
919
|
-
}
|
|
842
|
+
|
|
843
|
+
// Not called
|
|
844
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
845
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
846
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
847
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
848
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
849
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
850
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
851
|
+
|
|
852
|
+
// HCI state checks
|
|
853
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
854
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
855
|
+
expect(hci._aclConnections.get(4660)).toEqual({ pending: 3 });
|
|
856
|
+
expect(hci._aclConnections.get(4661)).toEqual({ pending: 2 });
|
|
857
|
+
|
|
858
|
+
// Check buffer was created properly
|
|
859
|
+
expect(hci._handleBuffers[1266]).toEqual({
|
|
860
|
+
length: 3,
|
|
861
|
+
cid: 2307,
|
|
862
|
+
data: expect.any(Buffer)
|
|
920
863
|
});
|
|
864
|
+
expect(Buffer.from(hci._handleBuffers[1266].data)).toEqual(Buffer.from([9, 8]));
|
|
921
865
|
});
|
|
922
|
-
|
|
923
|
-
|
|
866
|
+
|
|
867
|
+
test('should do nothing - HCI_ACLDATA_PKT / ACL_CONT without existing buffer', () => {
|
|
924
868
|
const eventType = 2;
|
|
925
869
|
const subEventTypeP1 = 0xf2;
|
|
926
870
|
const subEventTypeP2 = 0x14;
|
|
927
871
|
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8]);
|
|
928
872
|
hci.onSocketData(data);
|
|
929
|
-
|
|
930
|
-
// called
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
});
|
|
949
|
-
|
|
950
|
-
it('should concat data - HCI_ACLDATA_PKT / ACL_CONT', () => {
|
|
873
|
+
|
|
874
|
+
// Not called
|
|
875
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
876
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
877
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
878
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
879
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
880
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
881
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
882
|
+
|
|
883
|
+
// HCI state checks
|
|
884
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
885
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
886
|
+
expect(hci._aclConnections.get(4660)).toEqual({ pending: 3 });
|
|
887
|
+
expect(hci._aclConnections.get(4661)).toEqual({ pending: 2 });
|
|
888
|
+
expect(hci._handleBuffers).toEqual({});
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
test('should concat data - HCI_ACLDATA_PKT / ACL_CONT with existing buffer', () => {
|
|
951
892
|
const eventType = 2;
|
|
952
893
|
const subEventTypeP1 = 0xf2;
|
|
953
894
|
const subEventTypeP2 = 0x14;
|
|
954
895
|
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8]);
|
|
955
|
-
|
|
956
|
-
|
|
896
|
+
|
|
897
|
+
// Setup pre-existing buffer
|
|
898
|
+
hci._handleBuffers = {
|
|
957
899
|
1266: {
|
|
958
900
|
length: 3,
|
|
959
901
|
cid: 2307,
|
|
960
902
|
data: Buffer.from([3, 4])
|
|
961
903
|
}
|
|
962
904
|
};
|
|
963
|
-
|
|
964
|
-
|
|
905
|
+
|
|
965
906
|
hci.onSocketData(data);
|
|
966
|
-
|
|
967
|
-
// called
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
should(hci._handleBuffers).deepEqual({
|
|
907
|
+
|
|
908
|
+
// Not called
|
|
909
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
910
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
911
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
912
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
913
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
914
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
915
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
916
|
+
|
|
917
|
+
// HCI state checks
|
|
918
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
919
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
920
|
+
expect(hci._aclConnections.get(4660)).toEqual({ pending: 3 });
|
|
921
|
+
expect(hci._aclConnections.get(4661)).toEqual({ pending: 2 });
|
|
922
|
+
|
|
923
|
+
// Check buffer was updated properly
|
|
924
|
+
expect(hci._handleBuffers).toEqual({
|
|
985
925
|
1266: {
|
|
986
926
|
length: 3,
|
|
987
927
|
cid: 2307,
|
|
988
|
-
data:
|
|
928
|
+
data: expect.any(Buffer)
|
|
989
929
|
}
|
|
990
930
|
});
|
|
931
|
+
|
|
932
|
+
// Check buffer contents
|
|
933
|
+
const bufferData = hci._handleBuffers[1266].data;
|
|
934
|
+
expect(Buffer.from(bufferData)).toEqual(Buffer.from([3, 4, 3, 0, 3, 9, 9, 8]));
|
|
991
935
|
});
|
|
992
|
-
|
|
993
|
-
|
|
936
|
+
|
|
937
|
+
test('should concat data and emit aclDataPkt - HCI_ACLDATA_PKT / ACL_CONT when complete', () => {
|
|
994
938
|
const eventType = 2;
|
|
995
939
|
const subEventTypeP1 = 0xf2;
|
|
996
940
|
const subEventTypeP2 = 0x14;
|
|
997
941
|
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8]);
|
|
998
|
-
|
|
999
|
-
|
|
942
|
+
|
|
943
|
+
// Setup pre-existing buffer with enough expected length to trigger completion
|
|
944
|
+
hci._handleBuffers = {
|
|
1000
945
|
1266: {
|
|
1001
946
|
length: 8,
|
|
1002
947
|
cid: 2307,
|
|
1003
948
|
data: Buffer.from([3, 4])
|
|
1004
949
|
}
|
|
1005
950
|
};
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
hci.onSocketData(data);
|
|
1009
|
-
|
|
1010
|
-
// called
|
|
1011
|
-
assert.calledOnceWithExactly(aclDataPktCallback, 1266, 2307, Buffer.from([3, 4, 3, 0, 3, 9, 9, 8]));
|
|
1012
|
-
|
|
1013
|
-
// not called
|
|
1014
|
-
assert.notCalled(hci.flushAcl);
|
|
1015
|
-
assert.notCalled(hci.processLeMetaEvent);
|
|
1016
|
-
assert.notCalled(encryptChangeCallback);
|
|
1017
|
-
assert.notCalled(hci.processCmdCompleteEvent);
|
|
1018
|
-
assert.notCalled(disconnCompleteCallback);
|
|
1019
|
-
assert.notCalled(leScanEnableSetCmdCallback);
|
|
1020
|
-
|
|
1021
|
-
// hci checks
|
|
1022
|
-
should(hci._aclQueue).deepEqual(aclQueue);
|
|
1023
|
-
should(hci._aclConnections).have.keys(4660, 4661);
|
|
1024
|
-
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
|
|
1025
|
-
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
|
|
1026
|
-
|
|
1027
|
-
should(hci._handleBuffers).be.empty();
|
|
1028
|
-
});
|
|
1029
|
-
|
|
1030
|
-
it('should do nothing - HCI_ACLDATA_PKT / ??', () => {
|
|
1031
|
-
const eventType = 2;
|
|
1032
|
-
const subEventType = 122;
|
|
1033
|
-
const data = Buffer.from([eventType, subEventType, 0, 1, 0x34, 0x12, 3, 9, 9]);
|
|
951
|
+
|
|
1034
952
|
hci.onSocketData(data);
|
|
1035
|
-
|
|
1036
|
-
//
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
//
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
953
|
+
|
|
954
|
+
// Called
|
|
955
|
+
expect(aclDataPktCallback).toHaveBeenCalledWith(
|
|
956
|
+
1266,
|
|
957
|
+
2307,
|
|
958
|
+
expect.any(Buffer)
|
|
959
|
+
);
|
|
960
|
+
|
|
961
|
+
// Verify buffer contents in the callback
|
|
962
|
+
const callData = aclDataPktCallback.mock.calls[0][2];
|
|
963
|
+
expect(Buffer.from(callData)).toEqual(Buffer.from([3, 4, 3, 0, 3, 9, 9, 8]));
|
|
964
|
+
|
|
965
|
+
// Not called
|
|
966
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
967
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
968
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
969
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
970
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
971
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
972
|
+
|
|
973
|
+
// HCI state checks
|
|
974
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
975
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
976
|
+
expect(hci._aclConnections.get(4660)).toEqual({ pending: 3 });
|
|
977
|
+
expect(hci._aclConnections.get(4661)).toEqual({ pending: 2 });
|
|
978
|
+
|
|
979
|
+
// Buffer should be emptied after processing
|
|
980
|
+
expect(hci._handleBuffers).toEqual({});
|
|
1052
981
|
});
|
|
1053
|
-
|
|
1054
|
-
|
|
982
|
+
|
|
983
|
+
test('should emit leScanEnableSetCmd - HCI_COMMAND_PKT / LE_SET_SCAN_ENABLE_CMD', () => {
|
|
1055
984
|
const eventType = 1;
|
|
1056
985
|
const subEventTypeP1 = 0x0c;
|
|
1057
986
|
const subEventTypeP2 = 0x20;
|
|
1058
987
|
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x01, 0]);
|
|
1059
|
-
|
|
1060
|
-
const handleBuffers = {
|
|
1061
|
-
1266: {
|
|
1062
|
-
length: 8,
|
|
1063
|
-
cid: 2307,
|
|
1064
|
-
data: Buffer.from([3, 4])
|
|
1065
|
-
}
|
|
1066
|
-
};
|
|
1067
|
-
hci._handleBuffers = handleBuffers;
|
|
1068
|
-
|
|
988
|
+
|
|
1069
989
|
hci.onSocketData(data);
|
|
1070
|
-
|
|
1071
|
-
//
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
//
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
//
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
});
|
|
1086
|
-
|
|
1087
|
-
|
|
990
|
+
|
|
991
|
+
// Called
|
|
992
|
+
expect(leScanEnableSetCmdCallback).toHaveBeenCalledWith(true, false);
|
|
993
|
+
|
|
994
|
+
// Not called
|
|
995
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
996
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
997
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
998
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
999
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
1000
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
1001
|
+
|
|
1002
|
+
// HCI state checks
|
|
1003
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
1004
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
test('should not emit leScanEnableSetCmd - HCI_COMMAND_PKT / unknown command', () => {
|
|
1088
1008
|
const eventType = 1;
|
|
1089
1009
|
const subEventTypeP1 = 0x0c;
|
|
1090
|
-
const subEventTypeP2 = 0x21;
|
|
1010
|
+
const subEventTypeP2 = 0x21; // Different command code
|
|
1091
1011
|
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x01, 0]);
|
|
1092
|
-
|
|
1093
|
-
const handleBuffers = {
|
|
1094
|
-
1266: {
|
|
1095
|
-
length: 8,
|
|
1096
|
-
cid: 2307,
|
|
1097
|
-
data: Buffer.from([3, 4])
|
|
1098
|
-
}
|
|
1099
|
-
};
|
|
1100
|
-
hci._handleBuffers = handleBuffers;
|
|
1101
|
-
|
|
1012
|
+
|
|
1102
1013
|
hci.onSocketData(data);
|
|
1103
|
-
|
|
1104
|
-
// called
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
it('should do nothing - ?? / ???', () => {
|
|
1121
|
-
const eventType = 122;
|
|
1014
|
+
|
|
1015
|
+
// Not called
|
|
1016
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
1017
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
1018
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
1019
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
1020
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
1021
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
1022
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
1023
|
+
|
|
1024
|
+
// HCI state checks
|
|
1025
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
1026
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
1027
|
+
});
|
|
1028
|
+
|
|
1029
|
+
test('should do nothing - unknown event type', () => {
|
|
1030
|
+
const eventType = 122; // Unknown event type
|
|
1122
1031
|
const subEventTypeP1 = 0x0c;
|
|
1123
1032
|
const subEventTypeP2 = 0x21;
|
|
1124
1033
|
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x01, 0]);
|
|
1125
|
-
|
|
1126
|
-
const handleBuffers = {
|
|
1127
|
-
1266: {
|
|
1128
|
-
length: 8,
|
|
1129
|
-
cid: 2307,
|
|
1130
|
-
data: Buffer.from([3, 4])
|
|
1131
|
-
}
|
|
1132
|
-
};
|
|
1133
|
-
hci._handleBuffers = handleBuffers;
|
|
1134
|
-
|
|
1034
|
+
|
|
1135
1035
|
hci.onSocketData(data);
|
|
1136
|
-
|
|
1137
|
-
// called
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1036
|
+
|
|
1037
|
+
// Not called
|
|
1038
|
+
expect(leScanEnableSetCmdCallback).not.toHaveBeenCalled();
|
|
1039
|
+
expect(hci.flushAcl).not.toHaveBeenCalled();
|
|
1040
|
+
expect(hci.processLeMetaEvent).not.toHaveBeenCalled();
|
|
1041
|
+
expect(encryptChangeCallback).not.toHaveBeenCalled();
|
|
1042
|
+
expect(hci.processCmdCompleteEvent).not.toHaveBeenCalled();
|
|
1043
|
+
expect(disconnCompleteCallback).not.toHaveBeenCalled();
|
|
1044
|
+
expect(aclDataPktCallback).not.toHaveBeenCalled();
|
|
1045
|
+
|
|
1046
|
+
// HCI state checks
|
|
1047
|
+
expect(hci._aclQueue).toEqual(aclQueue);
|
|
1048
|
+
expect(Array.from(hci._aclConnections.keys())).toEqual(expect.arrayContaining([4660, 4661]));
|
|
1049
|
+
});
|
|
1050
|
+
});
|
|
1051
|
+
|
|
1052
|
+
// LE_READ_LOCAL_SUPPORTED_FEATURES tests
|
|
1053
|
+
describe('LE_READ_LOCAL_SUPPORTED_FEATURES', () => {
|
|
1054
|
+
beforeEach(() => {
|
|
1055
|
+
// Spy on methods rather than replacing them
|
|
1056
|
+
jest.spyOn(hci, 'setCodedPhySupport');
|
|
1057
|
+
jest.spyOn(hci, 'setEventMask');
|
|
1058
|
+
jest.spyOn(hci, 'setLeEventMask');
|
|
1059
|
+
jest.spyOn(hci, 'readLocalVersion');
|
|
1060
|
+
jest.spyOn(hci, 'writeLeHostSupported');
|
|
1061
|
+
jest.spyOn(hci, 'readLeHostSupported');
|
|
1062
|
+
jest.spyOn(hci, 'readLeBufferSize');
|
|
1063
|
+
jest.spyOn(hci, 'readBdAddr');
|
|
1064
|
+
|
|
1065
|
+
// Reset _isExtended flag
|
|
1066
|
+
hci._isExtended = false;
|
|
1067
|
+
});
|
|
1068
|
+
|
|
1069
|
+
afterEach(() => {
|
|
1070
|
+
jest.clearAllMocks();
|
|
1071
|
+
});
|
|
1072
|
+
|
|
1073
|
+
test('should not process on error status', () => {
|
|
1074
|
+
const cmd = 8195;
|
|
1075
|
+
const status = 1;
|
|
1076
|
+
const result = Buffer.from([0x00, 0x00, 0x00, 0x00]);
|
|
1077
|
+
|
|
1078
|
+
hci.processCmdCompleteEvent(cmd, status, result);
|
|
1079
|
+
|
|
1080
|
+
// Verify no methods were called
|
|
1081
|
+
expect(hci.setCodedPhySupport).not.toHaveBeenCalled();
|
|
1082
|
+
expect(hci.setEventMask).not.toHaveBeenCalled();
|
|
1083
|
+
expect(hci.setLeEventMask).not.toHaveBeenCalled();
|
|
1084
|
+
expect(hci.readLocalVersion).not.toHaveBeenCalled();
|
|
1085
|
+
expect(hci.writeLeHostSupported).not.toHaveBeenCalled();
|
|
1086
|
+
expect(hci.readLeHostSupported).not.toHaveBeenCalled();
|
|
1087
|
+
expect(hci.readLeBufferSize).not.toHaveBeenCalled();
|
|
1088
|
+
expect(hci.readBdAddr).not.toHaveBeenCalled();
|
|
1089
|
+
|
|
1090
|
+
expect(hci._isExtended).toBe(false);
|
|
1091
|
+
});
|
|
1092
|
+
|
|
1093
|
+
test('should process without extended features', () => {
|
|
1094
|
+
const cmd = 8195;
|
|
1095
|
+
const status = 0;
|
|
1096
|
+
const result = Buffer.from([0x00, 0x00, 0x00, 0x00]); // No bits set
|
|
1097
|
+
|
|
1098
|
+
hci.processCmdCompleteEvent(cmd, status, result);
|
|
1099
|
+
|
|
1100
|
+
// Verify extended-specific method not called
|
|
1101
|
+
expect(hci.setCodedPhySupport).not.toHaveBeenCalled();
|
|
1102
|
+
|
|
1103
|
+
// Verify other methods were called
|
|
1104
|
+
expect(hci.setEventMask).toHaveBeenCalled();
|
|
1105
|
+
expect(hci.setLeEventMask).toHaveBeenCalled();
|
|
1106
|
+
expect(hci.readLocalVersion).toHaveBeenCalled();
|
|
1107
|
+
expect(hci.writeLeHostSupported).toHaveBeenCalled();
|
|
1108
|
+
expect(hci.readLeHostSupported).toHaveBeenCalled();
|
|
1109
|
+
expect(hci.readLeBufferSize).toHaveBeenCalled();
|
|
1110
|
+
expect(hci.readBdAddr).toHaveBeenCalled();
|
|
1111
|
+
|
|
1112
|
+
expect(hci._isExtended).toBe(false);
|
|
1151
1113
|
});
|
|
1152
1114
|
});
|
|
1153
1115
|
|
|
@@ -1899,10 +1861,14 @@ describe('hci-socket hci', () => {
|
|
|
1899
1861
|
const data = Buffer.from([1, 0, 0xff, 0xee]);
|
|
1900
1862
|
const callback = sinon.spy();
|
|
1901
1863
|
|
|
1864
|
+
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
1865
|
+
|
|
1902
1866
|
hci.on('leAdvertisingReport', callback);
|
|
1903
1867
|
hci.processLeAdvertisingReport(count, data);
|
|
1904
1868
|
|
|
1905
1869
|
assert.notCalled(callback);
|
|
1870
|
+
|
|
1871
|
+
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('illegal packet'));
|
|
1906
1872
|
});
|
|
1907
1873
|
});
|
|
1908
1874
|
|
|
@@ -1947,10 +1913,13 @@ describe('hci-socket hci', () => {
|
|
|
1947
1913
|
const data = Buffer.from([1, 0, 0xff, 0xee]);
|
|
1948
1914
|
const callback = sinon.spy();
|
|
1949
1915
|
|
|
1916
|
+
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
1917
|
+
|
|
1950
1918
|
hci.on('leExtendedAdvertisingReport', callback);
|
|
1951
1919
|
hci.processLeExtendedAdvertisingReport(count, data);
|
|
1952
1920
|
|
|
1953
1921
|
assert.notCalled(callback);
|
|
1922
|
+
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('illegal packet'));
|
|
1954
1923
|
});
|
|
1955
1924
|
});
|
|
1956
1925
|
|