bluetooth-serial-port 2.2.5 → 3.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/.ccls-cache/@@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/@usr@local@Cellar@libuv@1.31.0@include@uv.h +1724 -0
- package/.ccls-cache/@@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/@usr@local@Cellar@libuv@1.31.0@include@uv.h.blob +0 -0
- package/.ccls-cache/@@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/@usr@local@Cellar@libuv@1.31.0@include@uv@darwin.h +61 -0
- package/.ccls-cache/@@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/@usr@local@Cellar@libuv@1.31.0@include@uv@darwin.h.blob +0 -0
- package/.ccls-cache/@@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/@usr@local@Cellar@libuv@1.31.0@include@uv@errno.h +443 -0
- package/.ccls-cache/@@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/@usr@local@Cellar@libuv@1.31.0@include@uv@errno.h.blob +0 -0
- package/.ccls-cache/@@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/@usr@local@Cellar@libuv@1.31.0@include@uv@threadpool.h +37 -0
- package/.ccls-cache/@@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/@usr@local@Cellar@libuv@1.31.0@include@uv@threadpool.h.blob +0 -0
- package/.ccls-cache/@@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/@usr@local@Cellar@libuv@1.31.0@include@uv@unix.h +491 -0
- package/.ccls-cache/@@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/@usr@local@Cellar@libuv@1.31.0@include@uv@unix.h.blob +0 -0
- package/.ccls-cache/@@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/@usr@local@Cellar@libuv@1.31.0@include@uv@version.h +43 -0
- package/.ccls-cache/@@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/@usr@local@Cellar@libuv@1.31.0@include@uv@version.h.blob +0 -0
- package/.ccls-cache/@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/src@DeviceINQ.h +78 -0
- package/.ccls-cache/@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/src@DeviceINQ.h.blob +0 -0
- package/.ccls-cache/@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/src@linux@BTSerialPortBinding.cc +404 -0
- package/.ccls-cache/@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/src@linux@BTSerialPortBinding.cc.blob +0 -0
- package/{src/osx/BluetoothSerialPort.mm → .ccls-cache/@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/src@linux@BluetoothSerialPort.cc} +3 -3
- package/.ccls-cache/@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/src@linux@BluetoothSerialPort.cc.blob +0 -0
- package/.ccls-cache/@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/src@linux@DeviceINQ.cc +369 -0
- package/.ccls-cache/@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/src@linux@DeviceINQ.cc.blob +0 -0
- package/.ccls-cache/@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/src@windows@BluetoothHelpers.h +24 -0
- package/.ccls-cache/@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/src@windows@BluetoothHelpers.h.blob +0 -0
- package/.ccls-cache/@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/src@windows@DeviceINQ.cc +527 -0
- package/.ccls-cache/@Users@eelco@Projects@Figaro@workspace@node-bluetooth-serial-port/src@windows@DeviceINQ.cc.blob +0 -0
- package/.circleci/config.yml +47 -0
- package/.github/dependabot.yml +11 -0
- package/Dockerfile +1 -1
- package/Dockerfile.bk +13 -0
- package/README.md +91 -78
- package/RELEASE_NOTES.md +14 -0
- package/appveyor.yml +6 -9
- package/binding.gyp +0 -8
- package/package.json +56 -58
- package/qemu-arm-static +0 -0
- package/src/BTSerialPortBinding.h +3 -3
- package/src/BTSerialPortBindingServer.h +1 -1
- package/src/DeviceINQ.h +1 -1
- package/src/linux/BTSerialPortBinding.cc +17 -15
- package/src/linux/BTSerialPortBindingServer.cc +29 -19
- package/src/linux/BluetoothSerialPort.cc +1 -1
- package/src/linux/BluetoothSerialPortServer.cc +1 -1
- package/src/linux/DeviceINQ.cc +18 -15
- package/src/{osx → macos}/BTSerialPortBinding.mm +23 -17
- package/src/{osx → macos}/BluetoothDeviceResources.h +0 -0
- package/src/{osx → macos}/BluetoothDeviceResources.mm +0 -0
- package/src/macos/BluetoothSerialPort.mm +23 -0
- package/src/{osx → macos}/BluetoothWorker.h +3 -3
- package/src/{osx → macos}/BluetoothWorker.mm +139 -140
- package/src/{osx → macos}/DeviceINQ.mm +21 -23
- package/src/{osx → macos}/pipe.c +0 -0
- package/src/{osx → macos}/pipe.h +0 -0
- package/src/windows/BTSerialPortBinding.cc +17 -18
- package/src/windows/BluetoothSerialPort.cc +3 -3
- package/src/windows/DeviceINQ.cc +17 -15
- package/.travis.yml +0 -48
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
#include <stdlib.h>
|
|
24
24
|
#include <unistd.h>
|
|
25
25
|
#include <node_object_wrap.h>
|
|
26
|
+
#include <dispatch/dispatch.h>
|
|
26
27
|
#include "pipe.h"
|
|
27
28
|
|
|
28
29
|
#ifndef RFCOMM_UUID
|
|
@@ -34,7 +35,7 @@ using namespace v8;
|
|
|
34
35
|
|
|
35
36
|
/** Private class for wrapping a pipe */
|
|
36
37
|
@interface Pipe : NSObject {
|
|
37
|
-
|
|
38
|
+
pipe_t *pipe;
|
|
38
39
|
}
|
|
39
40
|
@property (nonatomic, assign) pipe_t *pipe;
|
|
40
41
|
@end
|
|
@@ -46,8 +47,8 @@ using namespace v8;
|
|
|
46
47
|
|
|
47
48
|
/** Private class for wrapping data */
|
|
48
49
|
@interface BTData : NSObject {
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
NSData *data;
|
|
51
|
+
NSString *address;
|
|
51
52
|
}
|
|
52
53
|
@property (nonatomic, assign) NSData *data;
|
|
53
54
|
@property (nonatomic, assign) NSString *address;
|
|
@@ -102,193 +103,191 @@ static NSLock *globalConnectLock = nil;
|
|
|
102
103
|
deviceLock = [[NSLock alloc] init];
|
|
103
104
|
connectLock = [[NSLock alloc] init];
|
|
104
105
|
writeLock = [[NSLock alloc] init];
|
|
105
|
-
|
|
106
|
-
// creates a worker thread that handles all the asynchronous stuff
|
|
107
|
-
worker = [[NSThread alloc]initWithTarget: self selector: @selector(startBluetoothThread:) object: nil];
|
|
108
|
-
[worker start];
|
|
106
|
+
worker_queue = dispatch_queue_create("btworker", NULL);
|
|
109
107
|
return self;
|
|
110
108
|
}
|
|
111
109
|
|
|
112
|
-
/** Creates a run loop and sets a timer to keep the run loop alive */
|
|
113
|
-
- (void) startBluetoothThread: (id) arg
|
|
114
|
-
{
|
|
115
|
-
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
|
116
|
-
//schedule a timer so runMode won't stop immediately
|
|
117
|
-
keepAliveTimer = [[NSTimer alloc] initWithFireDate:[NSDate distantFuture]
|
|
118
|
-
interval:1 target:nil selector:nil userInfo:nil repeats:YES];
|
|
119
|
-
[runLoop addTimer:keepAliveTimer forMode:NSDefaultRunLoopMode];
|
|
120
|
-
[[NSRunLoop currentRunLoop] run];
|
|
121
|
-
}
|
|
122
|
-
|
|
123
110
|
/** Disconnect from a Bluetooth device */
|
|
124
111
|
- (void) disconnectFromDevice:(NSString *)address
|
|
125
112
|
{
|
|
126
|
-
|
|
127
|
-
|
|
113
|
+
// this function is called synchronous from javascript so it waits on the worker task to complete.
|
|
114
|
+
dispatch_sync(worker_queue, ^{
|
|
115
|
+
[self disconnectFromDeviceTask: address];
|
|
116
|
+
});
|
|
128
117
|
}
|
|
129
118
|
|
|
130
119
|
/** Task on the worker to disconnect from a Bluetooth device */
|
|
131
120
|
- (void) disconnectFromDeviceTask: (NSString *) address
|
|
132
121
|
{
|
|
133
|
-
|
|
134
|
-
|
|
122
|
+
// make it safe
|
|
123
|
+
[deviceLock lock];
|
|
135
124
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
125
|
+
if (res != nil) {
|
|
126
|
+
if (res.producer != NULL) {
|
|
127
|
+
pipe_producer_free(res.producer);
|
|
128
|
+
res.producer = NULL;
|
|
129
|
+
}
|
|
141
130
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
131
|
+
if (res.channel != NULL) {
|
|
132
|
+
[res.channel closeChannel];
|
|
133
|
+
res.channel = NULL;
|
|
134
|
+
}
|
|
146
135
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
136
|
+
if (res.device != NULL) {
|
|
137
|
+
[res.device closeConnection];
|
|
138
|
+
res.device = NULL;
|
|
139
|
+
}
|
|
151
140
|
|
|
152
141
|
res = nil;
|
|
153
|
-
|
|
142
|
+
}
|
|
154
143
|
|
|
155
|
-
|
|
144
|
+
[deviceLock unlock];
|
|
156
145
|
}
|
|
157
146
|
|
|
158
147
|
/** Connect to a Bluetooth device on a specific channel using a pipe to communicate with the main thread */
|
|
159
148
|
- (IOReturn)connectDevice: (NSString *) address onChannel: (int) channel withPipe: (pipe_t *)pipe
|
|
160
149
|
{
|
|
161
|
-
|
|
150
|
+
[connectLock lock];
|
|
162
151
|
|
|
163
|
-
|
|
164
|
-
|
|
152
|
+
Pipe *pipeObj = [[Pipe alloc] init];
|
|
153
|
+
pipeObj.pipe = pipe;
|
|
165
154
|
|
|
166
|
-
|
|
167
|
-
|
|
155
|
+
NSDictionary *parameters = [[NSDictionary alloc] initWithObjectsAndKeys:
|
|
156
|
+
address, @"address", [NSNumber numberWithInt: channel], @"channel", pipeObj, @"pipe", nil];
|
|
168
157
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
158
|
+
// connect to a device and wait for the result
|
|
159
|
+
dispatch_sync(worker_queue, ^{
|
|
160
|
+
[self connectDeviceTask:parameters];
|
|
161
|
+
});
|
|
162
|
+
IOReturn result = connectResult;
|
|
163
|
+
[connectLock unlock];
|
|
173
164
|
|
|
174
|
-
|
|
165
|
+
return result;
|
|
175
166
|
}
|
|
176
167
|
|
|
177
168
|
/** Task to connect to a specific device */
|
|
178
169
|
- (void)connectDeviceTask: (NSDictionary *)parameters
|
|
179
170
|
{
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
171
|
+
NSString *address = [parameters objectForKey:@"address"];
|
|
172
|
+
NSNumber *channelID = [parameters objectForKey:@"channel"];
|
|
173
|
+
pipe_t *pipe = ((Pipe *)[parameters objectForKey:@"pipe"]).pipe;
|
|
183
174
|
|
|
184
|
-
|
|
175
|
+
connectResult = kIOReturnError;
|
|
185
176
|
|
|
186
|
-
|
|
177
|
+
[deviceLock lock];
|
|
187
178
|
|
|
188
|
-
|
|
189
|
-
|
|
179
|
+
if (res == nil) {
|
|
180
|
+
IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:address];
|
|
190
181
|
|
|
191
|
-
|
|
192
|
-
|
|
182
|
+
if (device != nil) {
|
|
183
|
+
IOBluetoothRFCOMMChannel *channel = [[IOBluetoothRFCOMMChannel alloc] init];
|
|
193
184
|
[globalConnectLock lock];
|
|
194
|
-
|
|
185
|
+
if ([device openRFCOMMChannelSync: &channel withChannelID:[channelID intValue] delegate: self] == kIOReturnSuccess) {
|
|
195
186
|
[globalConnectLock unlock];
|
|
196
|
-
|
|
197
|
-
|
|
187
|
+
connectResult = kIOReturnSuccess;
|
|
188
|
+
pipe_producer_t *producer = pipe_producer_new(pipe);
|
|
198
189
|
res = [[BluetoothDeviceResources alloc] init];
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
190
|
+
res.device = device;
|
|
191
|
+
res.producer = producer;
|
|
192
|
+
res.channel = channel;
|
|
193
|
+
} else {
|
|
203
194
|
[globalConnectLock unlock];
|
|
204
195
|
}
|
|
205
|
-
|
|
206
|
-
|
|
196
|
+
}
|
|
197
|
+
}
|
|
207
198
|
|
|
208
|
-
|
|
199
|
+
[deviceLock unlock];
|
|
209
200
|
}
|
|
210
201
|
|
|
211
202
|
/** Write synchronized to a connected Bluetooth device */
|
|
212
203
|
- (IOReturn)writeAsync:(void *)data length:(UInt16)length toDevice: (NSString *)address
|
|
213
204
|
{
|
|
214
|
-
|
|
205
|
+
[writeLock lock];
|
|
215
206
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
207
|
+
BTData *writeData = [[BTData alloc] init];
|
|
208
|
+
writeData.data = [NSData dataWithBytes: data length: length];
|
|
209
|
+
writeData.address = address;
|
|
219
210
|
|
|
220
|
-
|
|
221
|
-
|
|
211
|
+
// wait for the write to be performed on the worker thread
|
|
212
|
+
dispatch_sync(worker_queue, ^{
|
|
213
|
+
[self writeAsyncTask:writeData];
|
|
214
|
+
});
|
|
222
215
|
|
|
223
|
-
|
|
224
|
-
|
|
216
|
+
IOReturn result = writeResult;
|
|
217
|
+
[writeLock unlock];
|
|
225
218
|
|
|
226
|
-
|
|
219
|
+
return result;
|
|
227
220
|
}
|
|
228
221
|
|
|
229
222
|
/** Task to do the writing */
|
|
230
223
|
- (void)writeAsyncTask:(BTData *)writeData
|
|
231
224
|
{
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
225
|
+
if (res != nil) {
|
|
226
|
+
char *idx = (char *)[writeData.data bytes];
|
|
227
|
+
ssize_t numBytesRemaining;
|
|
228
|
+
BluetoothRFCOMMMTU rfcommChannelMTU;
|
|
236
229
|
|
|
237
|
-
|
|
238
|
-
|
|
230
|
+
numBytesRemaining = [writeData.data length];
|
|
231
|
+
writeResult = kIOReturnSuccess;
|
|
239
232
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
233
|
+
// Get the RFCOMM Channel's MTU. Each write can only
|
|
234
|
+
// contain up to the MTU size number of bytes.
|
|
235
|
+
rfcommChannelMTU = [res.channel getMTU];
|
|
243
236
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
237
|
+
// Loop through the data until we have no more to send.
|
|
238
|
+
while ((writeResult == kIOReturnSuccess) && (numBytesRemaining > 0)) {
|
|
239
|
+
// finds how many bytes I can send:
|
|
240
|
+
ssize_t numBytesToWrite = ((numBytesRemaining > rfcommChannelMTU) ? rfcommChannelMTU : numBytesRemaining);
|
|
248
241
|
|
|
249
|
-
|
|
250
|
-
|
|
242
|
+
// Send the bytes
|
|
243
|
+
writeResult = [res.channel writeAsync:idx length:numBytesToWrite refcon:res];
|
|
251
244
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
245
|
+
// Updates the position in the buffer:
|
|
246
|
+
numBytesRemaining -= numBytesToWrite;
|
|
247
|
+
idx += numBytesToWrite;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
257
250
|
|
|
258
|
-
|
|
251
|
+
CFRunLoopStop(CFRunLoopGetCurrent());
|
|
259
252
|
}
|
|
260
253
|
|
|
261
254
|
- (void)rfcommChannelWriteComplete:(IOBluetoothRFCOMMChannel*)rfcommChannel refcon:(void*)refcon status:(IOReturn)error
|
|
262
255
|
{
|
|
263
|
-
|
|
256
|
+
CFRunLoopStop(CFRunLoopGetCurrent());
|
|
264
257
|
}
|
|
265
258
|
|
|
266
259
|
/** Inquire Bluetooth devices and send results through the given pipe */
|
|
267
260
|
- (void) inquireWithPipe: (pipe_t *)pipe
|
|
268
261
|
{
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
262
|
+
@synchronized(self) {
|
|
263
|
+
inquiryProducer = pipe_producer_new(pipe);
|
|
264
|
+
dispatch_async(worker_queue, ^{
|
|
265
|
+
[self inquiryTask];
|
|
266
|
+
});
|
|
267
|
+
}
|
|
273
268
|
}
|
|
274
269
|
|
|
275
270
|
/** Worker task to the the inquiry */
|
|
276
271
|
- (void) inquiryTask
|
|
277
272
|
{
|
|
278
|
-
IOBluetoothDeviceInquiry *bdi = [
|
|
279
|
-
|
|
280
|
-
|
|
273
|
+
IOBluetoothDeviceInquiry *bdi = [IOBluetoothDeviceInquiry inquiryWithDelegate:self];
|
|
274
|
+
// bdi.inquiryLength = 30;
|
|
275
|
+
[bdi start];
|
|
276
|
+
// [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 31]];
|
|
277
|
+
// [bdi stop];
|
|
281
278
|
}
|
|
282
279
|
|
|
283
280
|
/** Get the RFCOMM channel for a given device */
|
|
284
281
|
- (int) getRFCOMMChannelID: (NSString *) address
|
|
285
282
|
{
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
283
|
+
[sdpLock lock];
|
|
284
|
+
// call the task on the worker thread and wait for the result
|
|
285
|
+
dispatch_sync(worker_queue, ^{
|
|
286
|
+
[self getRFCOMMChannelIDTask:address];
|
|
287
|
+
});
|
|
288
|
+
int returnValue = lastChannelID;
|
|
289
|
+
[sdpLock unlock];
|
|
290
|
+
return returnValue;
|
|
292
291
|
}
|
|
293
292
|
|
|
294
293
|
/** Task to get the RFCOMM channel */
|
|
@@ -307,7 +306,7 @@ static NSLock *globalConnectLock = nil;
|
|
|
307
306
|
|
|
308
307
|
bool stop = false;
|
|
309
308
|
|
|
310
|
-
|
|
309
|
+
NSTimeInterval endTime = [[NSDate date] timeIntervalSince1970] + 60;
|
|
311
310
|
// if needed wait for a while for the sdp update
|
|
312
311
|
while (!stop && [[NSDate date] timeIntervalSince1970] < endTime) { // wait no more than 60 seconds for SDP update
|
|
313
312
|
currentServiceUpdate = [device getLastServicesUpdate];
|
|
@@ -329,63 +328,63 @@ static NSLock *globalConnectLock = nil;
|
|
|
329
328
|
if ([sr hasServiceFromArray: uuids]) {
|
|
330
329
|
BluetoothRFCOMMChannelID cid = -1;
|
|
331
330
|
if ([sr getRFCOMMChannelID: &cid] == kIOReturnSuccess) {
|
|
332
|
-
|
|
333
|
-
|
|
331
|
+
lastChannelID = cid;
|
|
332
|
+
return;
|
|
334
333
|
}
|
|
335
334
|
}
|
|
336
335
|
}
|
|
337
336
|
}
|
|
338
337
|
|
|
339
|
-
// This can happen
|
|
338
|
+
// This can happen in some conditions where the network is unreliable. Just ignore for now...
|
|
340
339
|
lastChannelID = -1;
|
|
341
340
|
}
|
|
342
341
|
|
|
343
342
|
/** Called when data is received from a remote device */
|
|
344
343
|
- (void)rfcommChannelData:(IOBluetoothRFCOMMChannel*)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength
|
|
345
344
|
{
|
|
346
|
-
|
|
345
|
+
NSData *data = [NSData dataWithBytes: dataPointer length: dataLength];
|
|
347
346
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
347
|
+
if (res != NULL && res.producer != NULL) {
|
|
348
|
+
// push the data into the pipe so it can be read from the main thread
|
|
349
|
+
pipe_push(res.producer, [data bytes], data.length);
|
|
350
|
+
}
|
|
352
351
|
|
|
353
|
-
|
|
352
|
+
CFRunLoopStop(CFRunLoopGetCurrent());
|
|
354
353
|
}
|
|
355
354
|
|
|
356
355
|
/** Called when a channel has been closed */
|
|
357
356
|
- (void)rfcommChannelClosed:(IOBluetoothRFCOMMChannel*)rfcommChannel
|
|
358
357
|
{
|
|
359
|
-
|
|
358
|
+
[self disconnectFromDevice: [[rfcommChannel getDevice] addressString]];
|
|
360
359
|
}
|
|
361
360
|
|
|
362
361
|
/** Called when the device inquiry completes */
|
|
363
362
|
- (void) deviceInquiryComplete: (IOBluetoothDeviceInquiry *) sender error: (IOReturn) error aborted: (BOOL) aborted
|
|
364
363
|
{
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
364
|
+
@synchronized(self) {
|
|
365
|
+
if (inquiryProducer != NULL) {
|
|
366
|
+
// free the producer so the main thread is signaled that the inquiry has been completed.
|
|
367
|
+
pipe_producer_free(inquiryProducer);
|
|
368
|
+
inquiryProducer = NULL;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
372
371
|
}
|
|
373
372
|
|
|
374
373
|
/** Called when a device has been found */
|
|
375
374
|
- (void) deviceInquiryDeviceFound: (IOBluetoothDeviceInquiry*) sender device: (IOBluetoothDevice*) device
|
|
376
375
|
{
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
376
|
+
@synchronized(self) {
|
|
377
|
+
if (inquiryProducer != NULL) {
|
|
378
|
+
device_info_t *info = new device_info_t;
|
|
379
|
+
strcpy(info->address, [[device addressString] UTF8String]);
|
|
380
|
+
strcpy(info->name, [[device addressString] UTF8String]);
|
|
381
|
+
|
|
382
|
+
// push the device data into the pipe to notify the main thread
|
|
383
|
+
pipe_push(inquiryProducer, info, 1);
|
|
384
|
+
|
|
385
|
+
delete info;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
389
388
|
}
|
|
390
389
|
|
|
391
390
|
@end
|
|
@@ -72,10 +72,10 @@ class InquireWorker : public Nan::AsyncWorker {
|
|
|
72
72
|
Nan::New(device.address).ToLocalChecked(),
|
|
73
73
|
Nan::New(device.name).ToLocalChecked()
|
|
74
74
|
};
|
|
75
|
-
found->Call(2, argv);
|
|
75
|
+
found->Call(2, argv, async_resource);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
callback->Call(0, 0);
|
|
78
|
+
callback->Call(0, 0, async_resource);
|
|
79
79
|
[inquiryResult release];
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -106,7 +106,7 @@ void DeviceINQ::EIO_AfterSdpSearch(uv_work_t *req) {
|
|
|
106
106
|
Local<Value> argv[] = {
|
|
107
107
|
Nan::New(baton->channelID)
|
|
108
108
|
};
|
|
109
|
-
baton->cb
|
|
109
|
+
Nan::Call(*baton->cb, 1, argv);
|
|
110
110
|
|
|
111
111
|
if (try_catch.HasCaught()) {
|
|
112
112
|
Nan::FatalException(try_catch);
|
|
@@ -118,7 +118,7 @@ void DeviceINQ::EIO_AfterSdpSearch(uv_work_t *req) {
|
|
|
118
118
|
baton = NULL;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
void DeviceINQ::Init(
|
|
121
|
+
void DeviceINQ::Init(Local<Object> target) {
|
|
122
122
|
Nan::HandleScope scope;
|
|
123
123
|
|
|
124
124
|
Local<FunctionTemplate> t = Nan::New<FunctionTemplate>(New);
|
|
@@ -126,15 +126,14 @@ void DeviceINQ::Init(Handle<Object> target) {
|
|
|
126
126
|
t->InstanceTemplate()->SetInternalFieldCount(1);
|
|
127
127
|
t->SetClassName(Nan::New("DeviceINQ").ToLocalChecked());
|
|
128
128
|
|
|
129
|
+
Isolate *isolate = target->GetIsolate();
|
|
130
|
+
Local<Context> ctx = isolate->GetCurrentContext();
|
|
131
|
+
|
|
129
132
|
Nan::SetPrototypeMethod(t, "inquireSync", InquireSync);
|
|
130
133
|
Nan::SetPrototypeMethod(t, "inquire", Inquire);
|
|
131
134
|
Nan::SetPrototypeMethod(t, "findSerialPortChannel", SdpSearch);
|
|
132
135
|
Nan::SetPrototypeMethod(t, "listPairedDevices", ListPairedDevices);
|
|
133
|
-
target->Set(Nan::New("DeviceINQ").ToLocalChecked(), t->GetFunction());
|
|
134
|
-
target->Set(Nan::New("DeviceINQ").ToLocalChecked(), t->GetFunction());
|
|
135
|
-
target->Set(Nan::New("DeviceINQ").ToLocalChecked(), t->GetFunction());
|
|
136
|
-
target->Set(Nan::New("DeviceINQ").ToLocalChecked(), t->GetFunction());
|
|
137
|
-
|
|
136
|
+
target->Set(ctx, Nan::New("DeviceINQ").ToLocalChecked(), t->GetFunction(ctx).ToLocalChecked());
|
|
138
137
|
}
|
|
139
138
|
|
|
140
139
|
NSArray *DeviceINQ::doInquire() {
|
|
@@ -216,6 +215,7 @@ NAN_METHOD(DeviceINQ::InquireSync) {
|
|
|
216
215
|
NSValue *boxedDevice;
|
|
217
216
|
NSArray *inquiryResult = doInquire();
|
|
218
217
|
NSEnumerator *enumerator = [inquiryResult objectEnumerator];
|
|
218
|
+
Nan::AsyncResource resource("bluetooth-serial-port:inqureSync");
|
|
219
219
|
while (boxedDevice = [enumerator nextObject]) {
|
|
220
220
|
struct bt_device device;
|
|
221
221
|
|
|
@@ -225,10 +225,10 @@ NAN_METHOD(DeviceINQ::InquireSync) {
|
|
|
225
225
|
Nan::New(device.name).ToLocalChecked()
|
|
226
226
|
};
|
|
227
227
|
|
|
228
|
-
found->Call(2, argv);
|
|
228
|
+
found->Call(2, argv, &resource);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
callback->Call(0, 0);
|
|
231
|
+
callback->Call(0, 0, &resource);
|
|
232
232
|
[inquiryResult release];
|
|
233
233
|
|
|
234
234
|
return;
|
|
@@ -243,7 +243,7 @@ NAN_METHOD(DeviceINQ::SdpSearch) {
|
|
|
243
243
|
if (!info[0]->IsString()) {
|
|
244
244
|
return Nan::ThrowTypeError("First argument should be a string value");
|
|
245
245
|
}
|
|
246
|
-
String::Utf8Value address(info[0]);
|
|
246
|
+
String::Utf8Value address(info.GetIsolate(), info[0]);
|
|
247
247
|
|
|
248
248
|
if(!info[1]->IsFunction()) {
|
|
249
249
|
return Nan::ThrowTypeError("Second argument must be a function");
|
|
@@ -294,8 +294,8 @@ NAN_METHOD(DeviceINQ::ListPairedDevices) {
|
|
|
294
294
|
|
|
295
295
|
Local<Object> deviceObj = Nan::New<v8::Object>();
|
|
296
296
|
|
|
297
|
-
|
|
298
|
-
|
|
297
|
+
Nan::Set(deviceObj, Nan::New("name").ToLocalChecked(), Nan::New([device.nameOrAddress UTF8String]).ToLocalChecked());
|
|
298
|
+
Nan::Set(deviceObj, Nan::New("address").ToLocalChecked(), Nan::New([device.addressString UTF8String]).ToLocalChecked());
|
|
299
299
|
|
|
300
300
|
// A device may have multiple services, so enumerate each one
|
|
301
301
|
Local<Array> servicesArray = Nan::New<v8::Array>((int)device.services.count);
|
|
@@ -305,26 +305,24 @@ NAN_METHOD(DeviceINQ::ListPairedDevices) {
|
|
|
305
305
|
[service getRFCOMMChannelID:&channelID];
|
|
306
306
|
|
|
307
307
|
Local<Object> serviceObj = Nan::New<v8::Object>();
|
|
308
|
-
|
|
308
|
+
Nan::Set(serviceObj, Nan::New("channel").ToLocalChecked(), Nan::New((int)channelID));
|
|
309
309
|
|
|
310
310
|
if ([service getServiceName])
|
|
311
|
-
|
|
311
|
+
Nan::Set(serviceObj, Nan::New("name").ToLocalChecked(), Nan::New([[service getServiceName] UTF8String]).ToLocalChecked());
|
|
312
312
|
else
|
|
313
|
-
|
|
313
|
+
Nan::Set(serviceObj, Nan::New("name").ToLocalChecked(), Nan::Undefined());
|
|
314
314
|
|
|
315
|
-
|
|
315
|
+
Nan::Set(servicesArray, j, serviceObj);
|
|
316
316
|
}
|
|
317
|
-
|
|
317
|
+
Nan::Set(deviceObj, Nan::New("services").ToLocalChecked(), servicesArray);
|
|
318
318
|
|
|
319
|
-
|
|
319
|
+
Nan::Set(resultArray, i, deviceObj);
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
Local<Value> argv[1] = {
|
|
323
323
|
resultArray
|
|
324
324
|
};
|
|
325
|
-
cb->Call(Nan::GetCurrentContext()->Global(), 1, argv);
|
|
325
|
+
cb->Call(Nan::GetCurrentContext(), Nan::GetCurrentContext()->Global(), 1, argv);
|
|
326
326
|
|
|
327
327
|
return;
|
|
328
328
|
}
|
|
329
|
-
|
|
330
|
-
|
package/src/{osx → macos}/pipe.c
RENAMED
|
File without changes
|
package/src/{osx → macos}/pipe.h
RENAMED
|
File without changes
|
|
@@ -61,9 +61,9 @@ void BTSerialPortBinding::EIO_AfterConnect(uv_work_t *req) {
|
|
|
61
61
|
connect_baton_t *baton = static_cast<connect_baton_t *>(req->data);
|
|
62
62
|
|
|
63
63
|
Nan::TryCatch try_catch;
|
|
64
|
-
|
|
64
|
+
Nan::AsyncResource resource("bluetooth-serial-port:Connect");
|
|
65
65
|
if (baton->status == 0) {
|
|
66
|
-
baton->cb->Call(0, nullptr);
|
|
66
|
+
baton->cb->Call(0, nullptr, &resource);
|
|
67
67
|
} else {
|
|
68
68
|
if (baton->rfcomm->s != INVALID_SOCKET) {
|
|
69
69
|
closesocket(baton->rfcomm->s);
|
|
@@ -74,7 +74,7 @@ void BTSerialPortBinding::EIO_AfterConnect(uv_work_t *req) {
|
|
|
74
74
|
Local<Value> argv[] = {
|
|
75
75
|
Nan::Error(msg)
|
|
76
76
|
};
|
|
77
|
-
baton->ecb->Call(1, argv);
|
|
77
|
+
baton->ecb->Call(1, argv, &resource);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
if (try_catch.HasCaught()) {
|
|
@@ -127,7 +127,8 @@ void BTSerialPortBinding::EIO_AfterWrite(uv_work_t *req) {
|
|
|
127
127
|
argv[1] = Nan::New<v8::Integer>(static_cast<int32_t>(data->result));
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
Nan::AsyncResource resource("bluetooth-serial-port:Write");
|
|
131
|
+
data->callback->Call(2, argv, &resource);
|
|
131
132
|
|
|
132
133
|
uv_mutex_lock(&write_queue_mutex);
|
|
133
134
|
ngx_queue_remove(&queuedWrite->queue);
|
|
@@ -187,18 +188,14 @@ void BTSerialPortBinding::EIO_AfterRead(uv_work_t *req) {
|
|
|
187
188
|
argv[0] = Nan::Error("Error reading from connection");
|
|
188
189
|
argv[1] = Nan::Undefined();
|
|
189
190
|
} else {
|
|
190
|
-
Local<Object>
|
|
191
|
-
Local<Function> bufferConstructor = Local<Function>::Cast(globalObj->Get(Nan::New("Buffer").ToLocalChecked()));
|
|
192
|
-
Local<Value> constructorArgs[1] = { Nan::New<v8::Integer>(baton->size) };
|
|
193
|
-
Local<Object> resultBuffer = Nan::NewInstance(bufferConstructor, 1, constructorArgs).ToLocalChecked();
|
|
194
|
-
|
|
191
|
+
Local<Object> resultBuffer = Nan::NewBuffer(baton->size).ToLocalChecked();
|
|
195
192
|
memcpy_s(Buffer::Data(resultBuffer), baton->size, baton->result, baton->size);
|
|
196
|
-
|
|
197
193
|
argv[0] = Nan::Undefined();
|
|
198
194
|
argv[1] = resultBuffer;
|
|
199
195
|
}
|
|
200
196
|
|
|
201
|
-
|
|
197
|
+
Nan::AsyncResource resource("bluetooth-serial-port:Read");
|
|
198
|
+
baton->cb->Call(2, argv, &resource);
|
|
202
199
|
|
|
203
200
|
if (try_catch.HasCaught()) {
|
|
204
201
|
Nan::FatalException(try_catch);
|
|
@@ -210,20 +207,21 @@ void BTSerialPortBinding::EIO_AfterRead(uv_work_t *req) {
|
|
|
210
207
|
baton = nullptr;
|
|
211
208
|
}
|
|
212
209
|
|
|
213
|
-
void BTSerialPortBinding::Init(
|
|
210
|
+
void BTSerialPortBinding::Init(Local<Object> target) {
|
|
214
211
|
Nan::HandleScope scope;
|
|
215
212
|
|
|
216
213
|
Local<FunctionTemplate> t = Nan::New<FunctionTemplate>(New);
|
|
217
214
|
|
|
215
|
+
Isolate *isolate = target->GetIsolate();
|
|
216
|
+
Local<Context> ctx = isolate->GetCurrentContext();
|
|
217
|
+
|
|
218
218
|
t->InstanceTemplate()->SetInternalFieldCount(1);
|
|
219
219
|
t->SetClassName(Nan::New("BTSerialPortBinding").ToLocalChecked());
|
|
220
220
|
|
|
221
221
|
Nan::SetPrototypeMethod(t, "write", Write);
|
|
222
222
|
Nan::SetPrototypeMethod(t, "read", Read);
|
|
223
223
|
Nan::SetPrototypeMethod(t, "close", Close);
|
|
224
|
-
target->Set(Nan::New("BTSerialPortBinding").ToLocalChecked(), t->GetFunction());
|
|
225
|
-
target->Set(Nan::New("BTSerialPortBinding").ToLocalChecked(), t->GetFunction());
|
|
226
|
-
target->Set(Nan::New("BTSerialPortBinding").ToLocalChecked(), t->GetFunction());
|
|
224
|
+
target->Set(ctx, Nan::New("BTSerialPortBinding").ToLocalChecked(), t->GetFunction(ctx).ToLocalChecked());
|
|
227
225
|
}
|
|
228
226
|
|
|
229
227
|
BTSerialPortBinding::BTSerialPortBinding() : s(INVALID_SOCKET) {
|
|
@@ -244,8 +242,8 @@ NAN_METHOD(BTSerialPortBinding::New) {
|
|
|
244
242
|
return Nan::ThrowError("usage: BTSerialPortBinding(address, channelID, callback, error)");
|
|
245
243
|
}
|
|
246
244
|
|
|
247
|
-
String::Utf8Value address(info[0]);
|
|
248
|
-
int channelID = info[1]->Int32Value();
|
|
245
|
+
String::Utf8Value address(info.GetIsolate(), info[0]);
|
|
246
|
+
int channelID = info[1]->Int32Value(Nan::GetCurrentContext()).ToChecked();
|
|
249
247
|
if (channelID <= 0) {
|
|
250
248
|
return Nan::ThrowTypeError("ChannelID should be a positive int value");
|
|
251
249
|
}
|
|
@@ -353,8 +351,9 @@ NAN_METHOD(BTSerialPortBinding::Read) {
|
|
|
353
351
|
argv[0] = Nan::Error("The connection has been closed");
|
|
354
352
|
argv[1] = Nan::Undefined();
|
|
355
353
|
|
|
354
|
+
Nan::AsyncResource resource("bluetooth-serial-port:Read");
|
|
356
355
|
Nan::Callback *nc = new Nan::Callback(cb);
|
|
357
|
-
nc->Call(2, argv);
|
|
356
|
+
nc->Call(2, argv, &resource);
|
|
358
357
|
} else {
|
|
359
358
|
read_baton_t *baton = new read_baton_t();
|
|
360
359
|
baton->rfcomm = rfcomm;
|