ftdi-d2xx
Version:
Pre-compiled FTDI D2XX drivers for Node.js (Node-API/CMake)
139 lines (101 loc) • 7.87 kB
Markdown
# FTDI D2XX Driver for Node.js
## Features
- Asynchronous, non-blocking functions (use [`Promises`](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Promises) or [`async/await`](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Promises#async_and_await))
- Pre-compiled for Windows / macOS / Linux
- Compatible with [Electron](https://www.electronjs.org/) (see [the note](#note-to-electron-users) below)
- Includes static FTDI Driver vendor libraries
- Written in pure C language using [Node-API](https://nodejs.org/api/n-api.html#node-api)
- Detailed error messages and codes are thrown without crashing Node.js
- Includes TypeScript typings for auto-completion and validation
- Compiled with [CMake.js](https://github.com/cmake-js/cmake-js) (no `gyp` / no Python required)
## Installation
In your Node.js project folder, run:
```bash
npm install ftdi-d2xx
```
On the top of your JavaScript file, add:
```js
const FTDI = require('ftdi-d2xx'); // CommonJS syntax (.js files)
// import FTDI from 'ftdi-d2xx'; // ESM syntax (.mjs files)
```
## Quick example
```js
let device;
async function quick_example() {
try {
// Get the connected devices info list
const list = await FTDI.getDeviceInfoList();
console.log(`${list.length} device${list.length>1?'s':''} found:`, list);
// If there is at least one device connected
if(list.length) {
// Try to open the first device from the list
device = await FTDI.openDevice(list[0].serial_number); // alternatively openDevice({ usb_loc_id: list[0].usb_loc_id });
console.log(`One device open:`, device);
// Setup the device
device.setTimeouts(1000, 1000); // set the max TX and RX duration in ms
device.purge(FTDI.FT_PURGE_RX); // purge the RX buffer from previous received data
//device.setBaudRate(115200); // set the UART baud rate (bits per second)
//device.setDataCharacteristics(FTDI.FT_BITS_8, FTDI.FT_STOP_BITS_1, FTDI.FT_PARITY_NONE);
// Send data from the TXD pin of the device
await device.write(Uint8Array.from([1, 2, 3, 4]));
console.log(`Data sent successfully.`);
// Wait to receive from the RXD pin
console.log(`Trying to receive data...`);
const response = await device.read(4); // expected response byte length (will return either if this is reached or after an RX timeout)
console.log(`${response.byteLength} bytes were received:`, response);
// If TXD and RXD pins are connected together, you should get Uint8Array(4)[1, 2, 3, 4] immediately
// If not, you should get Uint8Array(0)[] after 1 second of timeout
// Close the device (device object must then be recreated using openDevice)
device.close();
// Be careful "not to loose" the device object before closing it, otherwise
// the device will likely stay open and you will not be able to re-open it.
}
} catch (e) {
console.error(e);
}
}
// Run the example
await quick_example();
```
## Docs
- [FTDI D2XX Programmer's Guide](https://ftdichip.com/wp-content/uploads/2020/08/D2XX_Programmers_GuideFT_000071.pdf)
- [ftdi-d2xx JavaScript implementation API](docs/Home.md)
> [!NOTE]
> On Windows, FT_Reload() is implemented under FTDI.setVIDPID().
> [!NOTE]
> See the included FTDI D2XX driver library versions in the [CHANGELOG.md](CHANGELOG.md) file.
## Note to Electron users
As you may already know, Electron runs in two processes: a **main process** and a **renderer process** ([more info here](https://www.electronjs.org/docs/latest/tutorial/process-model)).
For security reasons, in the newest releases of Electron, you can only access Node.js inside the **main process**. However, you probably want to interact with this API using buttons, or to display information in the **renderer process**. It lets you two options:
- ***Option 1*** : Accessing this API only inside a `preload.js` file which has access to Node.js and can also export globals to the **renderer process** (recommended):
- This file shall be associated to the `BrowserWindow` of your application using `webPreferences.preload` field with `webPreferences.sandbox` set to `false` to enable external modules loading ([more info here](https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts)).
- This file shall contain (or require) all your functions calling this FTDI library.
- This file shall contain a `contextBridge` to expose your functions globally to the renderer process ([more info here](https://www.electronjs.org/docs/latest/api/context-bridge#usage)).
- **Important:** information exchanged in the pipe between **main process** and **renderer process** (Electron calls it IPC) is **serialized**. That means data is converted in a JSON-like file format before being passed. [Only these data types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#supported_types) are supported ([more info here](https://www.electronjs.org/docs/latest/tutorial/ipc#object-serialization)).
- **Note:** for the above reason, exposing the `FTDI` library object or functions directly to the **renderer process** doesn't work (it would be a bad security practice anyway).
- ***Option 2*** : Disabling the security and allowing Node.js to run in the **renderer process** ([more info here](https://www.electronjs.org/docs/latest/tutorial/security#2-do-not-enable-nodejs-integration-for-remote-content) - not recommended).
> [!IMPORTANT]
> If you use a compiler for your Electron project and you get errors, make sure to exclude this library from compilation as a native library.
## To do
To be added if there is a need for it:
- [ ] Add `FT_SetEventNotification` in a separate worker, with JS event handlers
- [ ] Add `FT_Rescan`, `FT_CyclePort`, `FT_SetResetPipeRetryCount`, `FT_StopInTask`, `FT_RestartInTask`, `FT_SetDeadmanTimeout`. Hopefully with the latest drivers and recent hardware, these functions are not needed anymore.
- [ ] Add `FT_SetChars` function
- [ ] Add the other `FT_EE_*` functions
## Development
- [Download and install CMake](https://cmake.org/download/) on your computer
- Clone this repository, add your modifications if needed
- Run `npm install` inside the repository to install development dependencies locally (cmake-js and typedoc)
- Compile the code:
- Running `npm run cmake:rebuild-debug` will rebuild the debug version of `ftdi-d2xx.node` for your platform and processor under `build/Debug`
- Running `npm run cmake:rebuild-release` will build `ftdi-d2xx.platform.processor.node` under `build/Release`
- Running `npm run cmake:clean` will clean the `build` folder
- Run `npm run node:test` to execute the `/test.js` file, which loads the Debug Build and runs basic initialization code followed by a REPL console to test function calls dynamically
- Run `npm run typedoc` to regenerate the API documentation
- Make a pull request to share your work
## Sponsor
The original work for the library wrapper has been sponsored by [ONWI](https://www.onwi.fr/), a small electronics design office and production unit based near Lyon, France.
## Licensing
This library is distributed under the terms of the [GNU LGPLv3](LICENSE).
It includes the official **libftd2xx** library provided by FTDI, which is released under their specific Driver Licence Terms (https://ftdichip.com/driver-licence-terms/). Please make sure you agree to all the License Terms before using this library. See the included library versions in the [CHANGELOG.md](CHANGELOG.md) file.
**libftd2xx** uses an unmodified version of libusb (http://libusb.info) which is distributed under the terms of the [GNU Lesser General Public License](https://www.gnu.org/licenses/lgpl-2.1.html). Source code for libusb is included in this distribution for reference (lib/libusb-source).