Skip to content

Commit a1217c0

Browse files
author
Marco Crespi
committed
fix(peripheral): Fix not using negotiated MTU
1 parent f04246f commit a1217c0

File tree

9 files changed

+115
-18
lines changed

9 files changed

+115
-18
lines changed

lib/bindings/hci/gatt/local/Gatt.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export declare class HciGattLocal extends GattLocal {
77
constructor(adapter: HciAdapter, hci: Hci, maxMtu?: number);
88
private onAclStreamData;
99
private errorResponse;
10+
private getMtu;
1011
private handleMtuRequest;
1112
private handleFindInfoRequest;
1213
private handleFindByTypeRequest;

lib/bindings/hci/gatt/local/Gatt.js

Lines changed: 9 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/bindings/hci/gatt/local/Gatt.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/models/gatt/local/Gatt.js

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/models/gatt/local/Gatt.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/bindings/hci/gatt/local/Gatt.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ export class HciGattLocal extends GattLocal {
9191
return buf;
9292
}
9393

94+
private getMtu(handle: number) {
95+
return this.negotiatedMtus.get(handle) || 23;
96+
}
97+
9498
private handleMtuRequest(_handle: number, _cid: number, request: Buffer) {
9599
let mtu = request.readUInt16LE(1);
96100

@@ -152,7 +156,7 @@ export class HciGattLocal extends GattLocal {
152156
}
153157

154158
const lengthPerInfo = uuidSize === 2 ? 4 : 18;
155-
const maxInfo = Math.floor((this._maxMtu - 2) / lengthPerInfo);
159+
const maxInfo = Math.floor((this.getMtu(_handle) - 2) / lengthPerInfo);
156160
numInfo = Math.min(numInfo, maxInfo);
157161

158162
response = Buffer.alloc(2 + numInfo * lengthPerInfo);
@@ -217,7 +221,7 @@ export class HciGattLocal extends GattLocal {
217221

218222
if (handles.length) {
219223
const lengthPerHandle = 4;
220-
const maxHandles = Math.floor((this._maxMtu - 1) / lengthPerHandle);
224+
const maxHandles = Math.floor((this.getMtu(_handle) - 1) / lengthPerHandle);
221225
const numHandles = Math.min(handles.length, maxHandles);
222226

223227
response = Buffer.alloc(1 + numHandles * lengthPerHandle);
@@ -274,7 +278,7 @@ export class HciGattLocal extends GattLocal {
274278
}
275279

276280
const lengthPerService = uuidSize === 2 ? 6 : 20;
277-
const maxServices = Math.floor((this._maxMtu - 2) / lengthPerService);
281+
const maxServices = Math.floor((this.getMtu(_handle) - 2) / lengthPerService);
278282
numServices = Math.min(numServices, maxServices);
279283

280284
response = Buffer.alloc(2 + numServices * lengthPerService);
@@ -345,7 +349,7 @@ export class HciGattLocal extends GattLocal {
345349
}
346350

347351
const lengthPerCharacteristic = uuidSize === 2 ? 7 : 21;
348-
const maxCharacteristics = Math.floor((this._maxMtu - 2) / lengthPerCharacteristic);
352+
const maxCharacteristics = Math.floor((this.getMtu(_handle) - 2) / lengthPerCharacteristic);
349353
numCharacteristics = Math.min(numCharacteristics, maxCharacteristics);
350354

351355
response = Buffer.alloc(2 + numCharacteristics * lengthPerCharacteristic);
@@ -408,7 +412,7 @@ export class HciGattLocal extends GattLocal {
408412
}
409413

410414
if (responseStatus === CONST.ATT_ECODE_SUCCESS) {
411-
const dataLength = Math.min(responseBuffer.length, this._maxMtu - 4);
415+
const dataLength = Math.min(responseBuffer.length, this.getMtu(_handle) - 4);
412416
response = Buffer.alloc(4 + dataLength);
413417

414418
response[0] = CONST.ATT_OP_READ_BY_TYPE_RESP;
@@ -485,7 +489,7 @@ export class HciGattLocal extends GattLocal {
485489

486490
if (result !== null) {
487491
if (result === CONST.ATT_ECODE_SUCCESS) {
488-
const dataLength = Math.min(data.length, this._maxMtu - 1);
492+
const dataLength = Math.min(data.length, this.getMtu(_handle) - 1);
489493
response = Buffer.alloc(1 + dataLength);
490494

491495
response[0] =

src/models/gatt/local/Gatt.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,18 @@ export abstract class GattLocal extends Gatt {
184184
object: newChar
185185
};
186186

187+
if (char.properties.includes('indicate') || char.properties.includes('notify')) {
188+
// notify or indicate: add client characteristic configuration descriptor
189+
const newDescr = new GattDescriptorLocal(newChar, '2902', Buffer.from([0x00, 0x00]));
190+
191+
const clientCharacteristicConfigurationDescriptorHandle = handle++;
192+
handles[clientCharacteristicConfigurationDescriptorHandle] = {
193+
type: 'descriptor',
194+
object: newDescr,
195+
value: clientCharacteristicConfigurationDescriptorHandle
196+
};
197+
}
198+
187199
if (char.descriptors) {
188200
for (const descr of char.descriptors) {
189201
const newDescr = new GattDescriptorLocal(newChar, descr.uuid, descr.value);

tests/advertise.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,29 @@ const main = async () => {
3838
const gatt = await adapter.setupGatt();
3939
gatt.setData(NAME, [
4040
{
41-
uuid: '48ee0000bf49460ca3d77ec7a512a4cd',
41+
uuid: '48ee0000bf49460ca3d77ec7a512a4ce',
4242
characteristics: [
4343
{
44-
uuid: '48ee0001bf49460ca3d77ec7a512a4cd',
45-
properties: ['read', 'write', 'write-without-response'],
44+
uuid: '48ee0001bf49460ca3d77ec7a512a4ce',
45+
properties: ['read'],
46+
secure: [],
47+
descriptors: [],
48+
value: Buffer.from('test', 'utf-8')
49+
},
50+
{
51+
uuid: '48ee0002bf49460ca3d77ec7a512a4ce',
52+
properties: ['read'],
53+
secure: [],
54+
descriptors: [],
55+
onRead: async (offset) => {
56+
return [0, Buffer.from('other', 'utf-8').slice(offset)];
57+
}
58+
},
59+
{
60+
uuid: '48ee0003bf49460ca3d77ec7a512a4cd',
61+
properties: ['write', 'write-without-response'],
4662
secure: [],
4763
descriptors: [],
48-
value: Buffer.from('1337'),
4964
onWrite: (offset, data, withoutResponse) => {
5065
console.log('writing', offset, data, withoutResponse);
5166
}

tests/bleno.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
var bleno = require('@abandonware/bleno');
2+
3+
const ADVERTISING_NAME = 'modum.io Gateway';
4+
const SERVICE_ID = '48ee0000bf49460ca3d77ec7a512a4ce';
5+
const OVERVIEW_CHAR_ID = '48ee0001bf49460ca3d77ec7a512a4ce';
6+
const TEST_CHAR_ID = '48ee0002bf49460ca3d77ec7a512a4ce';
7+
8+
bleno.on('stateChange', (state) => {
9+
console.log('state', state);
10+
11+
bleno.setServices(
12+
[
13+
new bleno.PrimaryService({
14+
uuid: SERVICE_ID,
15+
characteristics: [
16+
// Overview
17+
new bleno.Characteristic({
18+
uuid: OVERVIEW_CHAR_ID,
19+
properties: ['read'],
20+
secure: [],
21+
descriptors: [],
22+
onReadRequest: async (offset, callback) => {
23+
callback(bleno.Characteristic.RESULT_SUCCESS, Buffer.from('test', 'utf-8').slice(offset));
24+
}
25+
}),
26+
// Other
27+
new bleno.Characteristic({
28+
uuid: TEST_CHAR_ID,
29+
properties: ['read'],
30+
secure: [],
31+
descriptors: [],
32+
onReadRequest: async (offset, callback) => {
33+
if (offset === 0) {
34+
dataBuff = Buffer.from(data, 'utf-8');
35+
}
36+
37+
callback(bleno.Characteristic.RESULT_SUCCESS, Buffer.from('other', 'utf-8').slice(offset));
38+
}
39+
})
40+
]
41+
})
42+
],
43+
(err) => console.log('services', err)
44+
);
45+
46+
bleno.startAdvertising(ADVERTISING_NAME, [SERVICE_ID]);
47+
});
48+
bleno.on('advertisingStart', () => console.log('Advertising started'));
49+
bleno.on('advertisingStop', () => console.log('Advertising stopped'));
50+
bleno.on('accept', (clientAddress) => console.log('Connected', clientAddress));
51+
bleno.on('disconnect', (clientAddress) => console.log('Disonnected', clientAddress));
52+
bleno.on('error', (err) => console.error(err));

0 commit comments

Comments
 (0)