Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streams rewrite #906

Merged
merged 1 commit into from
Nov 5, 2016
Merged
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
4 changes: 2 additions & 2 deletions .docs/README.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,9 @@ port.write(new Buffer('Hi Mom!'));

Enjoy and do cool things with this code.

{{#modules~}}
{{#module name="serialport"}}
{{>members~}}
{{/modules}}
{{/module}}

## Command Line Tools
If you install `serialport` globally. (eg, `npm install -g serialport`) you'll receive two command line tools.
Expand Down
355 changes: 324 additions & 31 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
{
'sources': [
'src/serialport_unix.cpp',
'src/serialport_poller.cpp',
'src/read-poller.cpp',
],
'xcode_settings': {
'OTHER_LDFLAGS': [
Expand All @@ -41,7 +41,7 @@
{
'sources': [
'src/serialport_unix.cpp',
'src/serialport_poller.cpp',
'src/read-poller.cpp',
],
}
],
Expand Down
129 changes: 129 additions & 0 deletions lib/bindings-auto-detect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
'use strict';

/**
* @module serialport
*/

/**
* @name module:serialport.Binding
* @type {module:serialport~Binding}
* @description The Binding is how node SerialPort talks to the underlying system. By default we auto detect windows, Linux and OSX and load the appropriate module for your system. You can assign `SerialPort.Binding` to any backend you like. You can find more by searching on [npm](https://npmjs.org/).

You can also avoid auto loading the default backends by requiring SerialPort with
```js
var SerialPort = require('serialport/lib/serialport');
SerialPort.Binding = MyBindingClass;
```
*/

switch (process.platform) {
case 'win32':
module.exports = require('./bindings-win32');
break;
case 'darwin':
module.exports = require('./bindings-darwin');
break;
default:
module.exports = require('./bindings-linux');
}

/**
* You wont ever have to use Binding objects directly they'll be used by SerialPort to access the underlying hardware. This documentation is geared towards people making bindings for different platforms.
* @typedef {Class} Binding
* @class
* @param {object} options
* @param {function} options.disconnect - function to be called when the bindings have detected a disconnected port. This function should be called during any operation instead of that operations usual callback. The `SerialPort` class will attempt to call `close` after a disconnection and ignore any errors.
* @property {boolean} isOpen Required property. `true` if the port is open, `false` otherwise. Should be read only.
* @throws {TypeError} When given invalid arguments a TypeError will be thrown.
*/

/**
* Retrieves a list of available serial ports with metadata. The `comName` must be guaranteed and all the other fields should be undefined if they are unavailable. The `comName` is either the path or an identifier (eg `COM1`) used to open the serialport.
* @method module:serialport~Binding#list
* @param {module:serialport~listCallback} callback
*/

/**
* Opens a connection to the serial port referenced by the path.
* @method module:serialport~Binding#open
* @param {string} path
* @param {module:serialport~openOptions} openOptions
* @param {module:serialport~errorCallback} openCallback - is called after the data has been passed to the operating system for writing. This will only be called when there isn't a pending write operation.
* @throws {TypeError} When given invalid arguments a TypeError will be thrown.
*/

/**
* Closes an open connection
* @method module:serialport~Binding#close
* @param {module:serialport~errorCallback} callback Called once a connection is closed.
* @throws {TypeError} When given invalid arguments a TypeError will be thrown.
*/

/**
* Request a number of bytes from the SerialPort. This function is similar to node's [`fs.read`](http://nodejs.org/api/fs.html#fs_fs_read_fd_buffer_offset_length_position_callback).
* @method module:serialport~Binding#read
* @param {buffer} data - Accepts a [`Buffer`](http://nodejs.org/api/buffer.html) object.
* @params {integer} offset - is the offset in the buffer to start writing at.
* @param {integer} length - specifying the maximum number of bytes to read.
* @param {module:serialport~readCallback} readCallback - is called after a read operation
* @throws {TypeError} When given invalid arguments a TypeError will be thrown.
*/

/**
* A callback called with an error or null.
* @typedef {function} module:serialport~readCallback
* @param {?error} error
* @param {integer} bytesRead - the number of bytes that have been written into the buffer
* @param {buffer} buffer - the buffer that data was written into, same object that was passed into `read`.
* @throws {TypeError} When given invalid arguments a TypeError will be thrown.
*/

/**
* Write a number of bytes to the SerialPort
* @method module:serialport~Binding#write
* @param {buffer} data - Accepts a [`Buffer`](http://nodejs.org/api/buffer.html) object.
* @param {module:serialport~errorCallback} writeCallback - is called after the data has been passed to the operating system for writing. This will only be called when there isn't a pending write operation.
* @throws {TypeError} When given invalid arguments a TypeError will be thrown.
*/

/**
* Set control flags on an open port.
* @method module:serialport~Binding#set
* @param {object=} options All options are operating system default when the port is opened. Every flag is set on each call to the provided or default values. All options will always be provided.
* @param {Boolean} [options.brk=false]
* @param {Boolean} [options.cts=false]
* @param {Boolean} [options.dsr=false]
* @param {Boolean} [options.dtr=true]
* @param {Boolean} [options.rts=true]
* @param {module:serialport~errorCallback} callback Called once the port's flags have been set.
* @throws {TypeError} When given invalid arguments a TypeError will be thrown.
*/

/**
* Get the control flags (CTS, DSR, DCD) on the open port.
* @method module:serialport~Binding#get
* @param {module:serialport~modemBitsCallback=} callback Called once the flags have been retrieved.
* @throws {TypeError} When given invalid arguments a TypeError will be thrown.
*/

/**
* Flush (discard) data received but not read and written but not transmitted.
* @method module:serialport~Binding#flush
* @param {module:serialport~errorCallback} callback Called once the flush operation finishes.
* @throws {TypeError} When given invalid arguments a TypeError will be thrown.
*/

/**
* Drain waits until all output data has been transmitted to the serial port.
* @method module:serialport~Binding#drain
* @param {module:serialport~errorCallback} callback Called once the drain operation finishes.
* @throws {TypeError} When given invalid arguments a TypeError will be thrown.
*/

/**
* Changes options on an open port. Currently only the baudRate is required but any option could be passed to the bindings.
* @param {object=} options Only `baudRate` is currently supported
* @param {number=} [options.baudRate] If provided a baudRate that isn't supported by the bindings it should pass an error to the callback
* @param {module:serialport~errorCallback} [callback] Called once the port's baud rate has been changed.
* @throws {TypeError} When given invalid arguments a TypeError will be thrown.
*/
146 changes: 146 additions & 0 deletions lib/bindings-darwin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
'use strict';

var binding = require('bindings')('serialport.node');
var assign = require('object.assign').getPolyfill();

var defaultBindingOptions = {
vmin: 1,
vtime: 0
};

function asyncError(cb, err) {
process.nextTick(function() {
cb(err);
});
}

function DarwinBinding(opt) {
if (typeof opt !== 'object') {
throw new TypeError('options is not an object');
}
if (typeof opt.disconnect !== 'function') {
throw new TypeError('options.disconnect is not a function');
}
this.disconnect = opt.disconnect;
this.bindingOptions = opt.bindingOptions || {};
this.fd = null;
};

DarwinBinding.list = binding.list;

DarwinBinding.prototype.read = require('./read-unix');

DarwinBinding.prototype.open = function(path, options, cb) {
if (typeof path !== 'string') {
throw new TypeError('path is not a string');
}

if (typeof options !== 'object') {
throw new TypeError('options is not an object');
}

if (typeof cb !== 'function') {
throw new TypeError('cb is not a function');
}

if (this.isOpen) {
return asyncError(cb, new Error('Already open'));
}

options = assign({}, options, defaultBindingOptions, this.bindingOptions);

binding.open(path, options, function(err, fd) {
if (err) {
return cb(err);
}
this.fd = fd;
cb(null);
}.bind(this));
};

DarwinBinding.prototype.close = function(cb) {
if (typeof cb !== 'function') {
throw new TypeError('cb is not a function');
}

if (!this.isOpen) {
return asyncError(cb, new Error('Port is not open'));
}

if (this.readPoller) {
this.readPoller.stop();
this.readPoller = null;
}

binding.close(this.fd, function(err) {
if (err) {
return cb(err);
}
this.fd = null;
cb(null);
}.bind(this));
};

DarwinBinding.prototype.set = function(options, cb) {
if (typeof options !== 'object') {
throw new TypeError('options is not an object');
}

if (typeof cb !== 'function') {
throw new TypeError('cb is not a function');
}

if (!this.isOpen) {
return asyncError(cb, new Error('Port is not open'));
}
binding.set(this.fd, options, cb);
};

DarwinBinding.prototype.write = function(buffer, cb) {
if (!Buffer.isBuffer(buffer)) {
throw new TypeError('buffer is not a Buffer');
}

if (typeof cb !== 'function') {
throw new TypeError('cb is not a function');
}

if (!this.isOpen) {
return asyncError(cb, new Error('Port is not open'));
}

binding.write(this.fd, buffer, cb);
};

var commonMethods = [
'drain',
'flush',
'update',
'get'
];

commonMethods.map(function(methodName) {
DarwinBinding.prototype[methodName] = function() {
var args = Array.prototype.slice.apply(arguments);
var cb = args[args.length - 1];

if (typeof cb !== 'function') {
throw new TypeError('cb is not a function');
}

if (!this.isOpen) {
return asyncError(cb, new Error('Port is not open'));
}
args.unshift(this.fd);
binding[methodName].apply(binding, args);
};
});

Object.defineProperty(DarwinBinding.prototype, 'isOpen', {
enumerable: true,
get: function() {
return this.fd !== null;
}
});

module.exports = DarwinBinding;
Loading