Initial Commit

This commit is contained in:
2026-01-15 21:52:12 +01:00
committed by erik
parent 3ed42cdeb6
commit 5a70f775f1
6702 changed files with 1389544 additions and 0 deletions

21
node_modules/@serialport/bindings-cpp/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright 2010 Christopher Williams. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

95
node_modules/@serialport/bindings-cpp/README.md generated vendored Normal file
View File

@@ -0,0 +1,95 @@
# @serialport/bindings-cpp
[![Backers on Open Collective](https://opencollective.com/serialport/backers/badge.svg)](#backers)
[![Sponsors on Open Collective](https://opencollective.com/serialport/sponsors/badge.svg)](#sponsors)
[![codecov](https://codecov.io/gh/serialport/bindings-cpp/branch/main/graph/badge.svg?token=rsGeOmdnsV)](https://codecov.io/gh/serialport/bindings-cpp)
[![Test / Lint](https://github.com/serialport/bindings-cpp/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/serialport/bindings-cpp/actions/workflows/test.yml)
Access serial ports with JavaScript. Linux, OSX and Windows. Welcome your robotic JavaScript overlords. Better yet, program them!
> Go to https://serialport.io/ to learn more, find guides and api documentation.
## Quick Links
- 📚 [**Guides**](https://serialport.io/docs/)
- [**API Docs**](https://serialport.io/docs/api-serialport)
- [`@serialport/bindings-cpp`](https://www.npmjs.com/package/@serialport/bindings-cpp)
- 🐛 [Help and Bugs](https://github.com/serialport/node-serialport/issues/new/choose) All serialport issues are pointed to the main serialport repo.
### Bindings
The Bindings provide a low level interface to work with your serialport. It is possible to use them alone but it's usually easier to use them with an interface.
- [`@serialport/bindings-cpp`](https://serialport.io/docs/api-bindings-cpp) bindings for Linux, Mac and Windows
- [`@serialport/binding-interface`](https://serialport.io/docs/api-bindings-interface) as an interface to use if you're making your own bindings
- [`@serialport/binding-mock`](https://serialport.io/docs/api-binding-mock) for a mock binding package for testing
## Developing
### Developing node serialport projects
1. Clone this repo `git clone git@github.com:serialport/bindings-cpp.git`
1. Run `npm install` to setup local package dependencies (run this any time you depend on a package local to this repo)
1. Run `npm test` to ensure everything is working properly
1. If you have a serial loopback device (TX to RX) you can run run `TEST_PORT=/path/to/port npm test` for a more comprehensive test suite. (Defaults to 115200 baud customize with the TEST_BAUD env.) You can use an arduino with the `test/arduino-echo` sketch.
### Developing Docs
See https://github.com/serialport/website
## License
SerialPort packages are all [MIT licensed](LICENSE) and all it's dependencies are MIT licensed.
## Code of Conduct
SerialPort follows the [Nodebots Code of Conduct](http://nodebots.io/conduct.html). While the code is MIT licensed participation in the community has some rules to make this a good place to work and learn.
### TLDR
- Be respectful.
- Abusive behavior is never tolerated.
- Data published to NodeBots is hosted at the discretion of the service administrators, and may be removed.
- Don't build evil robots.
- Violations of this code may result in swift and permanent expulsion from the NodeBots community.
## Governance and Community
SerialPort is currently employees a [governance](https://medium.com/the-node-js-collection/healthy-open-source-967fa8be7951) with a group of maintainers, committers and contributors, all fixing bugs and adding features and improving documentation. You need not apply to work on SerialPort, all are welcome to join, build, and maintain this project.
- A Contributor is any individual creating or commenting on an issue or pull request. By participating, this is you.
- Committers are contributors who have been given write access to the repository. They can review and merge pull requests.
- Maintainers are committers representing the required technical expertise to resolve rare disputes.
If you have a PR that improves the project people in any or all of the above people will help you land it.
**Maintainers**
- [Francis Gulotta](https://twitter.com/reconbot) | [reconbot](https://github.com/reconbot)
- [Nick Hehr](https://twitter.com/hipsterbrown) | [hipsterbrown](https://github.com/hipsterbrown)
### Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
<a href="https://github.com/serialport/node-serialport/graphs/contributors"><img src="https://opencollective.com/serialport/contributors.svg?width=890&button=false" /></a>
### Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/serialport#backer)]
<a href="https://opencollective.com/serialport#backers" target="_blank"><img src="https://opencollective.com/serialport/backers.svg?width=890"></a>
### Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/serialport#sponsor)]
<!-- <a href="https://opencollective.com/serialport/sponsor/0/website" target="_blank"><img src="https://opencollective.com/serialport/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/serialport/sponsor/1/website" target="_blank"><img src="https://opencollective.com/serialport/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/serialport/sponsor/2/website" target="_blank"><img src="https://opencollective.com/serialport/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/serialport/sponsor/3/website" target="_blank"><img src="https://opencollective.com/serialport/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/serialport/sponsor/4/website" target="_blank"><img src="https://opencollective.com/serialport/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/serialport/sponsor/5/website" target="_blank"><img src="https://opencollective.com/serialport/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/serialport/sponsor/6/website" target="_blank"><img src="https://opencollective.com/serialport/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/serialport/sponsor/7/website" target="_blank"><img src="https://opencollective.com/serialport/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/serialport/sponsor/8/website" target="_blank"><img src="https://opencollective.com/serialport/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/serialport/sponsor/9/website" target="_blank"><img src="https://opencollective.com/serialport/sponsor/9/avatar.svg"></a> -->

Binary file not shown.

80
node_modules/@serialport/bindings-cpp/binding.gyp generated vendored Normal file
View File

@@ -0,0 +1,80 @@
{
'variables': {
'openssl_fips': ''
},
'targets': [{
'target_name': 'bindings',
'sources': [
'src/serialport.cpp'
],
'include_dirs': ["<!(node -p \"require('node-addon-api').include_dir\")"],
'cflags!': [ '-fno-exceptions' ],
'cflags_cc!': [ '-fno-exceptions' ],
"defines": ["NAPI_CPP_EXCEPTIONS"],
'conditions': [
['OS=="win"',
{
'defines': ['CHECK_NODE_MODULE_VERSION'],
'sources': [
'src/serialport_win.cpp'
],
'msvs_settings': {
'VCCLCompilerTool': {
'ExceptionHandling': '1',
'DisableSpecificWarnings': [ '4530', '4506' ],
}
}
}
],
['OS=="mac"',
{
'sources': [
'src/serialport_unix.cpp',
'src/poller.cpp',
'src/darwin_list.cpp'
],
'xcode_settings': {
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
'MACOSX_DEPLOYMENT_TARGET': '10.9',
'OTHER_CFLAGS': [
'-arch x86_64',
'-arch arm64'
],
'OTHER_LDFLAGS': [
'-framework CoreFoundation',
'-framework IOKit',
'-arch x86_64',
'-arch arm64'
]
}
}
],
['OS=="linux"',
{
'sources': [
'src/serialport_unix.cpp',
'src/poller.cpp',
'src/serialport_linux.cpp'
]
}
],
['OS=="android"',
{
'sources': [
'src/serialport_unix.cpp',
'src/poller.cpp',
'src/serialport_linux.cpp'
]
}
],
['OS!="win"',
{
'sources': [
'src/serialport_unix.cpp',
'src/poller.cpp'
]
}
]
]
}],
}

354
node_modules/@serialport/bindings-cpp/build/Makefile generated vendored Normal file
View File

@@ -0,0 +1,354 @@
# We borrow heavily from the kernel build setup, though we are simpler since
# we don't have Kconfig tweaking settings on us.
# The implicit make rules have it looking for RCS files, among other things.
# We instead explicitly write all the rules we care about.
# It's even quicker (saves ~200ms) to pass -r on the command line.
MAKEFLAGS=-r
# The source directory tree.
srcdir := ..
abs_srcdir := $(abspath $(srcdir))
# The name of the builddir.
builddir_name ?= .
# The V=1 flag on command line makes us verbosely print command lines.
ifdef V
quiet=
else
quiet=quiet_
endif
# Specify BUILDTYPE=Release on the command line for a release build.
BUILDTYPE ?= Release
# Directory all our build output goes into.
# Note that this must be two directories beneath src/ for unit tests to pass,
# as they reach into the src/ directory for data with relative paths.
builddir ?= $(builddir_name)/$(BUILDTYPE)
abs_builddir := $(abspath $(builddir))
depsdir := $(builddir)/.deps
# Object output directory.
obj := $(builddir)/obj
abs_obj := $(abspath $(obj))
# We build up a list of every single one of the targets so we can slurp in the
# generated dependency rule Makefiles in one pass.
all_deps :=
CC.target ?= $(CC)
CFLAGS.target ?= $(CPPFLAGS) $(CFLAGS)
CXX.target ?= $(CXX)
CXXFLAGS.target ?= $(CPPFLAGS) $(CXXFLAGS)
LINK.target ?= $(LINK)
LDFLAGS.target ?= $(LDFLAGS)
AR.target ?= $(AR)
PLI.target ?= pli
# C++ apps need to be linked with g++.
LINK ?= $(CXX.target)
# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
# to replicate this environment fallback in make as well.
CC.host ?= gcc
CFLAGS.host ?= $(CPPFLAGS_host) $(CFLAGS_host)
CXX.host ?= g++
CXXFLAGS.host ?= $(CPPFLAGS_host) $(CXXFLAGS_host)
LINK.host ?= $(CXX.host)
LDFLAGS.host ?= $(LDFLAGS_host)
AR.host ?= ar
PLI.host ?= pli
# Define a dir function that can handle spaces.
# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
# "leading spaces cannot appear in the text of the first argument as written.
# These characters can be put into the argument value by variable substitution."
empty :=
space := $(empty) $(empty)
# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
replace_spaces = $(subst $(space),?,$1)
unreplace_spaces = $(subst ?,$(space),$1)
dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
# Flags to make gcc output dependency info. Note that you need to be
# careful here to use the flags that ccache and distcc can understand.
# We write to a dep file on the side first and then rename at the end
# so we can't end up with a broken dep file.
depfile = $(depsdir)/$(call replace_spaces,$@).d
DEPFLAGS = -MMD -MF $(depfile).raw
# We have to fixup the deps output in a few ways.
# (1) the file output should mention the proper .o file.
# ccache or distcc lose the path to the target, so we convert a rule of
# the form:
# foobar.o: DEP1 DEP2
# into
# path/to/foobar.o: DEP1 DEP2
# (2) we want missing files not to cause us to fail to build.
# We want to rewrite
# foobar.o: DEP1 DEP2 \
# DEP3
# to
# DEP1:
# DEP2:
# DEP3:
# so if the files are missing, they're just considered phony rules.
# We have to do some pretty insane escaping to get those backslashes
# and dollar signs past make, the shell, and sed at the same time.
# Doesn't work with spaces, but that's fine: .d files have spaces in
# their names replaced with other characters.
define fixup_dep
# The depfile may not exist if the input file didn't have any #includes.
touch $(depfile).raw
# Fixup path as in (1).
sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
# Add extra rules as in (2).
# We remove slashes and replace spaces with new lines;
# remove blank lines;
# delete the first line and append a colon to the remaining lines.
sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
grep -v '^$$' |\
sed -e 1d -e 's|$$|:|' \
>> $(depfile)
rm $(depfile).raw
endef
# Command definitions:
# - cmd_foo is the actual command to run;
# - quiet_cmd_foo is the brief-output summary of the command.
quiet_cmd_cc = CC($(TOOLSET)) $@
cmd_cc = $(CC.$(TOOLSET)) -o $@ $< $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c
quiet_cmd_cxx = CXX($(TOOLSET)) $@
cmd_cxx = $(CXX.$(TOOLSET)) -o $@ $< $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c
quiet_cmd_touch = TOUCH $@
cmd_touch = touch $@
quiet_cmd_copy = COPY $@
# send stderr to /dev/null to ignore messages when linking directories.
cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
quiet_cmd_symlink = SYMLINK $@
cmd_symlink = ln -sf "$<" "$@"
quiet_cmd_alink = AR($(TOOLSET)) $@
cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
quiet_cmd_alink_thin = AR($(TOOLSET)) $@
cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^)
# Due to circular dependencies between libraries :(, we wrap the
# special "figure out circular dependencies" flags around the entire
# input list during linking.
quiet_cmd_link = LINK($(TOOLSET)) $@
cmd_link = $(LINK.$(TOOLSET)) -o $@ $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,--start-group $(LD_INPUTS) $(LIBS) -Wl,--end-group
# Note: this does not handle spaces in paths
define xargs
$(1) $(word 1,$(2))
$(if $(word 2,$(2)),$(call xargs,$(1),$(wordlist 2,$(words $(2)),$(2))))
endef
define write-to-file
@: >$(1)
$(call xargs,@printf "%s\n" >>$(1),$(2))
endef
OBJ_FILE_LIST := ar-file-list
define create_archive
rm -f $(1) $(1).$(OBJ_FILE_LIST); mkdir -p `dirname $(1)`
$(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2)))
$(AR.$(TOOLSET)) crs $(1) @$(1).$(OBJ_FILE_LIST)
endef
define create_thin_archive
rm -f $(1) $(OBJ_FILE_LIST); mkdir -p `dirname $(1)`
$(call write-to-file,$(1).$(OBJ_FILE_LIST),$(filter %.o,$(2)))
$(AR.$(TOOLSET)) crsT $(1) @$(1).$(OBJ_FILE_LIST)
endef
# We support two kinds of shared objects (.so):
# 1) shared_library, which is just bundling together many dependent libraries
# into a link line.
# 2) loadable_module, which is generating a module intended for dlopen().
#
# They differ only slightly:
# In the former case, we want to package all dependent code into the .so.
# In the latter case, we want to package just the API exposed by the
# outermost module.
# This means shared_library uses --whole-archive, while loadable_module doesn't.
# (Note that --whole-archive is incompatible with the --start-group used in
# normal linking.)
# Other shared-object link notes:
# - Set SONAME to the library filename so our binaries don't reference
# the local, absolute paths used on the link command-line.
quiet_cmd_solink = SOLINK($(TOOLSET)) $@
cmd_solink = $(LINK.$(TOOLSET)) -o $@ -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
cmd_solink_module = $(LINK.$(TOOLSET)) -o $@ -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
# Define an escape_quotes function to escape single quotes.
# This allows us to handle quotes properly as long as we always use
# use single quotes and escape_quotes.
escape_quotes = $(subst ','\'',$(1))
# This comment is here just to include a ' to unconfuse syntax highlighting.
# Define an escape_vars function to escape '$' variable syntax.
# This allows us to read/write command lines with shell variables (e.g.
# $LD_LIBRARY_PATH), without triggering make substitution.
escape_vars = $(subst $$,$$$$,$(1))
# Helper that expands to a shell command to echo a string exactly as it is in
# make. This uses printf instead of echo because printf's behaviour with respect
# to escape sequences is more portable than echo's across different shells
# (e.g., dash, bash).
exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
# Helper to compare the command we're about to run against the command
# we logged the last time we ran the command. Produces an empty
# string (false) when the commands match.
# Tricky point: Make has no string-equality test function.
# The kernel uses the following, but it seems like it would have false
# positives, where one string reordered its arguments.
# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
# $(filter-out $(cmd_$@), $(cmd_$(1))))
# We instead substitute each for the empty string into the other, and
# say they're equal if both substitutions produce the empty string.
# .d files contain ? instead of spaces, take that into account.
command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
$(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
# Helper that is non-empty when a prerequisite changes.
# Normally make does this implicitly, but we force rules to always run
# so we can check their command lines.
# $? -- new prerequisites
# $| -- order-only dependencies
prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
# Helper that executes all postbuilds until one fails.
define do_postbuilds
@E=0;\
for p in $(POSTBUILDS); do\
eval $$p;\
E=$$?;\
if [ $$E -ne 0 ]; then\
break;\
fi;\
done;\
if [ $$E -ne 0 ]; then\
rm -rf "$@";\
exit $$E;\
fi
endef
# do_cmd: run a command via the above cmd_foo names, if necessary.
# Should always run for a given target to handle command-line changes.
# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
# Third argument, if non-zero, makes it do POSTBUILDS processing.
# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
# spaces already and dirx strips the ? characters.
define do_cmd
$(if $(or $(command_changed),$(prereq_changed)),
@$(call exact_echo, $($(quiet)cmd_$(1)))
@mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
$(if $(findstring flock,$(word 1,$(cmd_$1))),
@$(cmd_$(1))
@echo " $(quiet_cmd_$(1)): Finished",
@$(cmd_$(1))
)
@$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
@$(if $(2),$(fixup_dep))
$(if $(and $(3), $(POSTBUILDS)),
$(call do_postbuilds)
)
)
endef
# Declare the "all" target first so it is the default,
# even though we don't have the deps yet.
.PHONY: all
all:
# make looks for ways to re-generate included makefiles, but in our case, we
# don't have a direct way. Explicitly telling make that it has nothing to do
# for them makes it go faster.
%.d: ;
# Use FORCE_DO_CMD to force a target to run. Should be coupled with
# do_cmd.
.PHONY: FORCE_DO_CMD
FORCE_DO_CMD:
TOOLSET := target
# Suffix rules, putting all outputs into $(obj).
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
@$(call do_cmd,cc,1)
# Try building from generated source, too.
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
@$(call do_cmd,cc,1)
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,bindings.target.mk)))),)
include bindings.target.mk
endif
quiet_cmd_regen_makefile = ACTION Regenerating $@
cmd_regen_makefile = cd $(srcdir); /home/erik/.npm/_npx/c78fbb4f3949be78/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/home/erik/.electron-gyp/28.3.3" "-Dnode_gyp_dir=/home/erik/.npm/_npx/c78fbb4f3949be78/node_modules/node-gyp" "-Dnode_lib_file=/home/erik/.electron-gyp/28.3.3/<(target_arch)/node.lib" "-Dmodule_root_dir=/home/erik/Dokumente/PackControl/node_modules/@serialport/bindings-cpp" "-Dnode_engine=v8" "--depth=." "-Goutput_dir=." "--generator-output=build" -I/home/erik/Dokumente/PackControl/node_modules/@serialport/bindings-cpp/build/config.gypi -I/home/erik/.npm/_npx/c78fbb4f3949be78/node_modules/node-gyp/addon.gypi -I/home/erik/.electron-gyp/28.3.3/include/node/common.gypi "--toplevel-dir=." binding.gyp
Makefile: $(srcdir)/build/config.gypi $(srcdir)/../../../../../.electron-gyp/28.3.3/include/node/common.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../.npm/_npx/c78fbb4f3949be78/node_modules/node-gyp/addon.gypi
$(call do_cmd,regen_makefile)
# "all" is a concatenation of the "all" targets from all the included
# sub-makefiles. This is just here to clarify.
all:
# Add in dependency-tracking rules. $(all_deps) is the list of every single
# target in our tree. Only consider the ones with .d (dependency) info:
d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
ifneq ($(d_files),)
include $(d_files)
endif

View File

@@ -0,0 +1 @@
cmd_Release/bindings.node := ln -f "Release/obj.target/bindings.node" "Release/bindings.node" 2>/dev/null || (rm -rf "Release/bindings.node" && cp -af "Release/obj.target/bindings.node" "Release/bindings.node")

View File

@@ -0,0 +1 @@
cmd_Release/obj.target/bindings.node := g++ -o Release/obj.target/bindings.node -shared -pthread -rdynamic -m64 -Wl,-soname=bindings.node -Wl,--start-group Release/obj.target/bindings/src/serialport.o Release/obj.target/bindings/src/serialport_unix.o Release/obj.target/bindings/src/poller.o Release/obj.target/bindings/src/serialport_linux.o -Wl,--end-group

View File

@@ -0,0 +1,32 @@
cmd_Release/obj.target/bindings/src/poller.o := g++ -o Release/obj.target/bindings/src/poller.o ../src/poller.cpp '-DNODE_GYP_MODULE_NAME=bindings' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-DV8_DEPRECATION_WARNINGS' '-DV8_IMMINENT_DEPRECATION_WARNINGS' '-D_GLIBCXX_USE_CXX11_ABI=1' '-DELECTRON_ENSURE_CONFIG_GYPI' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DUSING_ELECTRON_CONFIG_GYPI' '-DV8_COMPRESS_POINTERS' '-DV8_COMPRESS_POINTERS_IN_SHARED_CAGE' '-DV8_ENABLE_SANDBOX' '-DV8_31BIT_SMIS_ON_64BIT_ARCH' '-D__STDC_FORMAT_MACROS' '-DOPENSSL_NO_PINSHARED' '-DOPENSSL_THREADS' '-DOPENSSL_NO_ASM' '-DNAPI_CPP_EXCEPTIONS' '-DBUILDING_NODE_EXTENSION' -I/home/erik/.electron-gyp/28.3.3/include/node -I/home/erik/.electron-gyp/28.3.3/src -I/home/erik/.electron-gyp/28.3.3/deps/openssl/config -I/home/erik/.electron-gyp/28.3.3/deps/openssl/openssl/include -I/home/erik/.electron-gyp/28.3.3/deps/uv/include -I/home/erik/.electron-gyp/28.3.3/deps/zlib -I/home/erik/.electron-gyp/28.3.3/deps/v8/include -I../../../node-addon-api -fPIC -pthread -Wall -Wextra -Wno-unused-parameter -m64 -O3 -fno-omit-frame-pointer -fno-rtti -std=gnu++17 -MMD -MF ./Release/.deps/Release/obj.target/bindings/src/poller.o.d.raw -std=c++17 -c
Release/obj.target/bindings/src/poller.o: ../src/poller.cpp \
../../../node-addon-api/napi.h \
/home/erik/.electron-gyp/28.3.3/include/node/node_api.h \
/home/erik/.electron-gyp/28.3.3/include/node/js_native_api.h \
/home/erik/.electron-gyp/28.3.3/include/node/js_native_api_types.h \
/home/erik/.electron-gyp/28.3.3/include/node/node_api_types.h \
../../../node-addon-api/napi-inl.h ../../../node-addon-api/napi.h \
../../../node-addon-api/napi-inl.deprecated.h \
/home/erik/.electron-gyp/28.3.3/include/node/uv.h \
/home/erik/.electron-gyp/28.3.3/include/node/uv/errno.h \
/home/erik/.electron-gyp/28.3.3/include/node/uv/version.h \
/home/erik/.electron-gyp/28.3.3/include/node/uv/unix.h \
/home/erik/.electron-gyp/28.3.3/include/node/uv/threadpool.h \
/home/erik/.electron-gyp/28.3.3/include/node/uv/linux.h \
../src/./poller.h
../src/poller.cpp:
../../../node-addon-api/napi.h:
/home/erik/.electron-gyp/28.3.3/include/node/node_api.h:
/home/erik/.electron-gyp/28.3.3/include/node/js_native_api.h:
/home/erik/.electron-gyp/28.3.3/include/node/js_native_api_types.h:
/home/erik/.electron-gyp/28.3.3/include/node/node_api_types.h:
../../../node-addon-api/napi-inl.h:
../../../node-addon-api/napi.h:
../../../node-addon-api/napi-inl.deprecated.h:
/home/erik/.electron-gyp/28.3.3/include/node/uv.h:
/home/erik/.electron-gyp/28.3.3/include/node/uv/errno.h:
/home/erik/.electron-gyp/28.3.3/include/node/uv/version.h:
/home/erik/.electron-gyp/28.3.3/include/node/uv/unix.h:
/home/erik/.electron-gyp/28.3.3/include/node/uv/threadpool.h:
/home/erik/.electron-gyp/28.3.3/include/node/uv/linux.h:
../src/./poller.h:

View File

@@ -0,0 +1,35 @@
cmd_Release/obj.target/bindings/src/serialport.o := g++ -o Release/obj.target/bindings/src/serialport.o ../src/serialport.cpp '-DNODE_GYP_MODULE_NAME=bindings' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-DV8_DEPRECATION_WARNINGS' '-DV8_IMMINENT_DEPRECATION_WARNINGS' '-D_GLIBCXX_USE_CXX11_ABI=1' '-DELECTRON_ENSURE_CONFIG_GYPI' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DUSING_ELECTRON_CONFIG_GYPI' '-DV8_COMPRESS_POINTERS' '-DV8_COMPRESS_POINTERS_IN_SHARED_CAGE' '-DV8_ENABLE_SANDBOX' '-DV8_31BIT_SMIS_ON_64BIT_ARCH' '-D__STDC_FORMAT_MACROS' '-DOPENSSL_NO_PINSHARED' '-DOPENSSL_THREADS' '-DOPENSSL_NO_ASM' '-DNAPI_CPP_EXCEPTIONS' '-DBUILDING_NODE_EXTENSION' -I/home/erik/.electron-gyp/28.3.3/include/node -I/home/erik/.electron-gyp/28.3.3/src -I/home/erik/.electron-gyp/28.3.3/deps/openssl/config -I/home/erik/.electron-gyp/28.3.3/deps/openssl/openssl/include -I/home/erik/.electron-gyp/28.3.3/deps/uv/include -I/home/erik/.electron-gyp/28.3.3/deps/zlib -I/home/erik/.electron-gyp/28.3.3/deps/v8/include -I../../../node-addon-api -fPIC -pthread -Wall -Wextra -Wno-unused-parameter -m64 -O3 -fno-omit-frame-pointer -fno-rtti -std=gnu++17 -MMD -MF ./Release/.deps/Release/obj.target/bindings/src/serialport.o.d.raw -std=c++17 -c
Release/obj.target/bindings/src/serialport.o: ../src/serialport.cpp \
../src/./serialport.h \
/home/erik/.electron-gyp/28.3.3/include/node/node_version.h \
../../../node-addon-api/napi.h \
/home/erik/.electron-gyp/28.3.3/include/node/node_api.h \
/home/erik/.electron-gyp/28.3.3/include/node/js_native_api.h \
/home/erik/.electron-gyp/28.3.3/include/node/js_native_api_types.h \
/home/erik/.electron-gyp/28.3.3/include/node/node_api_types.h \
../../../node-addon-api/napi-inl.h ../../../node-addon-api/napi.h \
../../../node-addon-api/napi-inl.deprecated.h ../src/./poller.h \
/home/erik/.electron-gyp/28.3.3/include/node/uv.h \
/home/erik/.electron-gyp/28.3.3/include/node/uv/errno.h \
/home/erik/.electron-gyp/28.3.3/include/node/uv/version.h \
/home/erik/.electron-gyp/28.3.3/include/node/uv/unix.h \
/home/erik/.electron-gyp/28.3.3/include/node/uv/threadpool.h \
/home/erik/.electron-gyp/28.3.3/include/node/uv/linux.h
../src/serialport.cpp:
../src/./serialport.h:
/home/erik/.electron-gyp/28.3.3/include/node/node_version.h:
../../../node-addon-api/napi.h:
/home/erik/.electron-gyp/28.3.3/include/node/node_api.h:
/home/erik/.electron-gyp/28.3.3/include/node/js_native_api.h:
/home/erik/.electron-gyp/28.3.3/include/node/js_native_api_types.h:
/home/erik/.electron-gyp/28.3.3/include/node/node_api_types.h:
../../../node-addon-api/napi-inl.h:
../../../node-addon-api/napi.h:
../../../node-addon-api/napi-inl.deprecated.h:
../src/./poller.h:
/home/erik/.electron-gyp/28.3.3/include/node/uv.h:
/home/erik/.electron-gyp/28.3.3/include/node/uv/errno.h:
/home/erik/.electron-gyp/28.3.3/include/node/uv/version.h:
/home/erik/.electron-gyp/28.3.3/include/node/uv/unix.h:
/home/erik/.electron-gyp/28.3.3/include/node/uv/threadpool.h:
/home/erik/.electron-gyp/28.3.3/include/node/uv/linux.h:

View File

@@ -0,0 +1,4 @@
cmd_Release/obj.target/bindings/src/serialport_linux.o := g++ -o Release/obj.target/bindings/src/serialport_linux.o ../src/serialport_linux.cpp '-DNODE_GYP_MODULE_NAME=bindings' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-DV8_DEPRECATION_WARNINGS' '-DV8_IMMINENT_DEPRECATION_WARNINGS' '-D_GLIBCXX_USE_CXX11_ABI=1' '-DELECTRON_ENSURE_CONFIG_GYPI' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DUSING_ELECTRON_CONFIG_GYPI' '-DV8_COMPRESS_POINTERS' '-DV8_COMPRESS_POINTERS_IN_SHARED_CAGE' '-DV8_ENABLE_SANDBOX' '-DV8_31BIT_SMIS_ON_64BIT_ARCH' '-D__STDC_FORMAT_MACROS' '-DOPENSSL_NO_PINSHARED' '-DOPENSSL_THREADS' '-DOPENSSL_NO_ASM' '-DNAPI_CPP_EXCEPTIONS' '-DBUILDING_NODE_EXTENSION' -I/home/erik/.electron-gyp/28.3.3/include/node -I/home/erik/.electron-gyp/28.3.3/src -I/home/erik/.electron-gyp/28.3.3/deps/openssl/config -I/home/erik/.electron-gyp/28.3.3/deps/openssl/openssl/include -I/home/erik/.electron-gyp/28.3.3/deps/uv/include -I/home/erik/.electron-gyp/28.3.3/deps/zlib -I/home/erik/.electron-gyp/28.3.3/deps/v8/include -I../../../node-addon-api -fPIC -pthread -Wall -Wextra -Wno-unused-parameter -m64 -O3 -fno-omit-frame-pointer -fno-rtti -std=gnu++17 -MMD -MF ./Release/.deps/Release/obj.target/bindings/src/serialport_linux.o.d.raw -std=c++17 -c
Release/obj.target/bindings/src/serialport_linux.o: \
../src/serialport_linux.cpp
../src/serialport_linux.cpp:

View File

@@ -0,0 +1,24 @@
cmd_Release/obj.target/bindings/src/serialport_unix.o := g++ -o Release/obj.target/bindings/src/serialport_unix.o ../src/serialport_unix.cpp '-DNODE_GYP_MODULE_NAME=bindings' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-DV8_DEPRECATION_WARNINGS' '-DV8_IMMINENT_DEPRECATION_WARNINGS' '-D_GLIBCXX_USE_CXX11_ABI=1' '-DELECTRON_ENSURE_CONFIG_GYPI' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DUSING_ELECTRON_CONFIG_GYPI' '-DV8_COMPRESS_POINTERS' '-DV8_COMPRESS_POINTERS_IN_SHARED_CAGE' '-DV8_ENABLE_SANDBOX' '-DV8_31BIT_SMIS_ON_64BIT_ARCH' '-D__STDC_FORMAT_MACROS' '-DOPENSSL_NO_PINSHARED' '-DOPENSSL_THREADS' '-DOPENSSL_NO_ASM' '-DNAPI_CPP_EXCEPTIONS' '-DBUILDING_NODE_EXTENSION' -I/home/erik/.electron-gyp/28.3.3/include/node -I/home/erik/.electron-gyp/28.3.3/src -I/home/erik/.electron-gyp/28.3.3/deps/openssl/config -I/home/erik/.electron-gyp/28.3.3/deps/openssl/openssl/include -I/home/erik/.electron-gyp/28.3.3/deps/uv/include -I/home/erik/.electron-gyp/28.3.3/deps/zlib -I/home/erik/.electron-gyp/28.3.3/deps/v8/include -I../../../node-addon-api -fPIC -pthread -Wall -Wextra -Wno-unused-parameter -m64 -O3 -fno-omit-frame-pointer -fno-rtti -std=gnu++17 -MMD -MF ./Release/.deps/Release/obj.target/bindings/src/serialport_unix.o.d.raw -std=c++17 -c
Release/obj.target/bindings/src/serialport_unix.o: \
../src/serialport_unix.cpp ../src/serialport_unix.h ../src/serialport.h \
/home/erik/.electron-gyp/28.3.3/include/node/node_version.h \
../../../node-addon-api/napi.h \
/home/erik/.electron-gyp/28.3.3/include/node/node_api.h \
/home/erik/.electron-gyp/28.3.3/include/node/js_native_api.h \
/home/erik/.electron-gyp/28.3.3/include/node/js_native_api_types.h \
/home/erik/.electron-gyp/28.3.3/include/node/node_api_types.h \
../../../node-addon-api/napi-inl.h ../../../node-addon-api/napi.h \
../../../node-addon-api/napi-inl.deprecated.h ../src/serialport_linux.h
../src/serialport_unix.cpp:
../src/serialport_unix.h:
../src/serialport.h:
/home/erik/.electron-gyp/28.3.3/include/node/node_version.h:
../../../node-addon-api/napi.h:
/home/erik/.electron-gyp/28.3.3/include/node/node_api.h:
/home/erik/.electron-gyp/28.3.3/include/node/js_native_api.h:
/home/erik/.electron-gyp/28.3.3/include/node/js_native_api_types.h:
/home/erik/.electron-gyp/28.3.3/include/node/node_api_types.h:
../../../node-addon-api/napi-inl.h:
../../../node-addon-api/napi.h:
../../../node-addon-api/napi-inl.deprecated.h:
../src/serialport_linux.h:

View File

@@ -0,0 +1 @@
x64--119

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,6 @@
# This file is generated by gyp; do not edit.
export builddir_name ?= ./build/.
.PHONY: all
all:
$(MAKE) bindings

View File

@@ -0,0 +1,178 @@
# This file is generated by gyp; do not edit.
TOOLSET := target
TARGET := bindings
DEFS_Debug := \
'-DNODE_GYP_MODULE_NAME=bindings' \
'-DUSING_UV_SHARED=1' \
'-DUSING_V8_SHARED=1' \
'-DV8_DEPRECATION_WARNINGS=1' \
'-DV8_DEPRECATION_WARNINGS' \
'-DV8_IMMINENT_DEPRECATION_WARNINGS' \
'-D_GLIBCXX_USE_CXX11_ABI=1' \
'-DELECTRON_ENSURE_CONFIG_GYPI' \
'-D_LARGEFILE_SOURCE' \
'-D_FILE_OFFSET_BITS=64' \
'-DUSING_ELECTRON_CONFIG_GYPI' \
'-DV8_COMPRESS_POINTERS' \
'-DV8_COMPRESS_POINTERS_IN_SHARED_CAGE' \
'-DV8_ENABLE_SANDBOX' \
'-DV8_31BIT_SMIS_ON_64BIT_ARCH' \
'-D__STDC_FORMAT_MACROS' \
'-DOPENSSL_NO_PINSHARED' \
'-DOPENSSL_THREADS' \
'-DOPENSSL_NO_ASM' \
'-DNAPI_CPP_EXCEPTIONS' \
'-DBUILDING_NODE_EXTENSION' \
'-DDEBUG' \
'-D_DEBUG' \
'-DV8_ENABLE_CHECKS'
# Flags passed to all source files.
CFLAGS_Debug := \
-fPIC \
-pthread \
-Wall \
-Wextra \
-Wno-unused-parameter \
-m64 \
-g \
-O0
# Flags passed to only C files.
CFLAGS_C_Debug :=
# Flags passed to only C++ files.
CFLAGS_CC_Debug := \
-fno-rtti \
-std=gnu++17
INCS_Debug := \
-I/home/erik/.electron-gyp/28.3.3/include/node \
-I/home/erik/.electron-gyp/28.3.3/src \
-I/home/erik/.electron-gyp/28.3.3/deps/openssl/config \
-I/home/erik/.electron-gyp/28.3.3/deps/openssl/openssl/include \
-I/home/erik/.electron-gyp/28.3.3/deps/uv/include \
-I/home/erik/.electron-gyp/28.3.3/deps/zlib \
-I/home/erik/.electron-gyp/28.3.3/deps/v8/include \
-I$(srcdir)/../../node-addon-api
DEFS_Release := \
'-DNODE_GYP_MODULE_NAME=bindings' \
'-DUSING_UV_SHARED=1' \
'-DUSING_V8_SHARED=1' \
'-DV8_DEPRECATION_WARNINGS=1' \
'-DV8_DEPRECATION_WARNINGS' \
'-DV8_IMMINENT_DEPRECATION_WARNINGS' \
'-D_GLIBCXX_USE_CXX11_ABI=1' \
'-DELECTRON_ENSURE_CONFIG_GYPI' \
'-D_LARGEFILE_SOURCE' \
'-D_FILE_OFFSET_BITS=64' \
'-DUSING_ELECTRON_CONFIG_GYPI' \
'-DV8_COMPRESS_POINTERS' \
'-DV8_COMPRESS_POINTERS_IN_SHARED_CAGE' \
'-DV8_ENABLE_SANDBOX' \
'-DV8_31BIT_SMIS_ON_64BIT_ARCH' \
'-D__STDC_FORMAT_MACROS' \
'-DOPENSSL_NO_PINSHARED' \
'-DOPENSSL_THREADS' \
'-DOPENSSL_NO_ASM' \
'-DNAPI_CPP_EXCEPTIONS' \
'-DBUILDING_NODE_EXTENSION'
# Flags passed to all source files.
CFLAGS_Release := \
-fPIC \
-pthread \
-Wall \
-Wextra \
-Wno-unused-parameter \
-m64 \
-O3 \
-fno-omit-frame-pointer
# Flags passed to only C files.
CFLAGS_C_Release :=
# Flags passed to only C++ files.
CFLAGS_CC_Release := \
-fno-rtti \
-std=gnu++17
INCS_Release := \
-I/home/erik/.electron-gyp/28.3.3/include/node \
-I/home/erik/.electron-gyp/28.3.3/src \
-I/home/erik/.electron-gyp/28.3.3/deps/openssl/config \
-I/home/erik/.electron-gyp/28.3.3/deps/openssl/openssl/include \
-I/home/erik/.electron-gyp/28.3.3/deps/uv/include \
-I/home/erik/.electron-gyp/28.3.3/deps/zlib \
-I/home/erik/.electron-gyp/28.3.3/deps/v8/include \
-I$(srcdir)/../../node-addon-api
OBJS := \
$(obj).target/$(TARGET)/src/serialport.o \
$(obj).target/$(TARGET)/src/serialport_unix.o \
$(obj).target/$(TARGET)/src/poller.o \
$(obj).target/$(TARGET)/src/serialport_linux.o
# Add to the list of files we specially track dependencies for.
all_deps += $(OBJS)
# CFLAGS et al overrides must be target-local.
# See "Target-specific Variable Values" in the GNU Make manual.
$(OBJS): TOOLSET := $(TOOLSET)
$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
# Suffix rules, putting all outputs into $(obj).
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
@$(call do_cmd,cxx,1)
# Try building from generated source, too.
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
@$(call do_cmd,cxx,1)
# End of this set of suffix rules
### Rules for final target.
LDFLAGS_Debug := \
-pthread \
-rdynamic \
-m64
LDFLAGS_Release := \
-pthread \
-rdynamic \
-m64
LIBS :=
$(obj).target/bindings.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
$(obj).target/bindings.node: LIBS := $(LIBS)
$(obj).target/bindings.node: TOOLSET := $(TOOLSET)
$(obj).target/bindings.node: $(OBJS) FORCE_DO_CMD
$(call do_cmd,solink_module)
all_deps += $(obj).target/bindings.node
# Add target alias
.PHONY: bindings
bindings: $(builddir)/bindings.node
# Copy this to the executable output path.
$(builddir)/bindings.node: TOOLSET := $(TOOLSET)
$(builddir)/bindings.node: $(obj).target/bindings.node FORCE_DO_CMD
$(call do_cmd,copy)
all_deps += $(builddir)/bindings.node
# Short alias for building this executable.
.PHONY: bindings.node
bindings.node: $(obj).target/bindings.node $(builddir)/bindings.node
# Add executable to "all" target.
.PHONY: all
all: $(builddir)/bindings.node

422
node_modules/@serialport/bindings-cpp/build/config.gypi generated vendored Normal file
View File

@@ -0,0 +1,422 @@
# Do not edit. File was generated by node-gyp's "configure" step
{
"target_defaults": {
"cflags": [],
"default_configuration": "Release",
"defines": [],
"include_dirs": [],
"libraries": []
},
"variables": {
"asan": 0,
"build_v8_with_gn": "false",
"built_with_electron": 1,
"coverage": "false",
"dcheck_always_on": 0,
"debug_nghttp2": "false",
"debug_node": "false",
"enable_lto": "false",
"enable_pgo_generate": "false",
"enable_pgo_use": "false",
"error_on_warn": "false",
"force_dynamic_crt": 0,
"host_arch": "x64",
"icu_data_in": "..\\..\\deps\\icu-tmp\\icudt73l.dat",
"icu_endianness": "l",
"icu_gyp_path": "tools/icu/icu-generic.gyp",
"icu_path": "deps/icu-small",
"icu_small": "false",
"icu_ver_major": "73",
"is_debug": 0,
"libdir": "lib",
"llvm_version": "0.0",
"napi_build_version": "9",
"node_builtin_shareable_builtins": [
"deps/cjs-module-lexer/lexer.js",
"deps/cjs-module-lexer/dist/lexer.js",
"deps/undici/undici.js"
],
"node_byteorder": "little",
"node_debug_lib": "false",
"node_enable_d8": "false",
"node_enable_v8_vtunejit": "false",
"node_fipsinstall": "false",
"node_install_corepack": "true",
"node_install_npm": "true",
"node_library_files": [
"lib/_http_agent.js",
"lib/_http_client.js",
"lib/_http_common.js",
"lib/_http_incoming.js",
"lib/_http_outgoing.js",
"lib/_http_server.js",
"lib/_stream_duplex.js",
"lib/_stream_passthrough.js",
"lib/_stream_readable.js",
"lib/_stream_transform.js",
"lib/_stream_wrap.js",
"lib/_stream_writable.js",
"lib/_tls_common.js",
"lib/_tls_wrap.js",
"lib/assert.js",
"lib/assert/strict.js",
"lib/async_hooks.js",
"lib/buffer.js",
"lib/child_process.js",
"lib/cluster.js",
"lib/console.js",
"lib/constants.js",
"lib/crypto.js",
"lib/dgram.js",
"lib/diagnostics_channel.js",
"lib/dns.js",
"lib/dns/promises.js",
"lib/domain.js",
"lib/events.js",
"lib/fs.js",
"lib/fs/promises.js",
"lib/http.js",
"lib/http2.js",
"lib/https.js",
"lib/inspector.js",
"lib/internal/abort_controller.js",
"lib/internal/assert.js",
"lib/internal/assert/assertion_error.js",
"lib/internal/assert/calltracker.js",
"lib/internal/async_hooks.js",
"lib/internal/blob.js",
"lib/internal/blocklist.js",
"lib/internal/bootstrap/browser.js",
"lib/internal/bootstrap/loaders.js",
"lib/internal/bootstrap/node.js",
"lib/internal/bootstrap/switches/does_not_own_process_state.js",
"lib/internal/bootstrap/switches/does_own_process_state.js",
"lib/internal/bootstrap/switches/is_main_thread.js",
"lib/internal/bootstrap/switches/is_not_main_thread.js",
"lib/internal/buffer.js",
"lib/internal/child_process.js",
"lib/internal/child_process/serialization.js",
"lib/internal/cli_table.js",
"lib/internal/cluster/child.js",
"lib/internal/cluster/primary.js",
"lib/internal/cluster/round_robin_handle.js",
"lib/internal/cluster/shared_handle.js",
"lib/internal/cluster/utils.js",
"lib/internal/cluster/worker.js",
"lib/internal/console/constructor.js",
"lib/internal/console/global.js",
"lib/internal/constants.js",
"lib/internal/crypto/aes.js",
"lib/internal/crypto/certificate.js",
"lib/internal/crypto/cfrg.js",
"lib/internal/crypto/cipher.js",
"lib/internal/crypto/diffiehellman.js",
"lib/internal/crypto/ec.js",
"lib/internal/crypto/hash.js",
"lib/internal/crypto/hashnames.js",
"lib/internal/crypto/hkdf.js",
"lib/internal/crypto/keygen.js",
"lib/internal/crypto/keys.js",
"lib/internal/crypto/mac.js",
"lib/internal/crypto/pbkdf2.js",
"lib/internal/crypto/random.js",
"lib/internal/crypto/rsa.js",
"lib/internal/crypto/scrypt.js",
"lib/internal/crypto/sig.js",
"lib/internal/crypto/util.js",
"lib/internal/crypto/webcrypto.js",
"lib/internal/crypto/webidl.js",
"lib/internal/crypto/x509.js",
"lib/internal/debugger/inspect.js",
"lib/internal/debugger/inspect_client.js",
"lib/internal/debugger/inspect_repl.js",
"lib/internal/dgram.js",
"lib/internal/dns/callback_resolver.js",
"lib/internal/dns/promises.js",
"lib/internal/dns/utils.js",
"lib/internal/dtrace.js",
"lib/internal/encoding.js",
"lib/internal/error_serdes.js",
"lib/internal/errors.js",
"lib/internal/event_target.js",
"lib/internal/file.js",
"lib/internal/fixed_queue.js",
"lib/internal/freelist.js",
"lib/internal/freeze_intrinsics.js",
"lib/internal/fs/cp/cp-sync.js",
"lib/internal/fs/cp/cp.js",
"lib/internal/fs/dir.js",
"lib/internal/fs/promises.js",
"lib/internal/fs/read_file_context.js",
"lib/internal/fs/recursive_watch.js",
"lib/internal/fs/rimraf.js",
"lib/internal/fs/streams.js",
"lib/internal/fs/sync_write_stream.js",
"lib/internal/fs/utils.js",
"lib/internal/fs/watchers.js",
"lib/internal/heap_utils.js",
"lib/internal/histogram.js",
"lib/internal/http.js",
"lib/internal/http2/compat.js",
"lib/internal/http2/core.js",
"lib/internal/http2/util.js",
"lib/internal/idna.js",
"lib/internal/inspector_async_hook.js",
"lib/internal/js_stream_socket.js",
"lib/internal/legacy/processbinding.js",
"lib/internal/linkedlist.js",
"lib/internal/main/check_syntax.js",
"lib/internal/main/environment.js",
"lib/internal/main/eval_stdin.js",
"lib/internal/main/eval_string.js",
"lib/internal/main/inspect.js",
"lib/internal/main/mksnapshot.js",
"lib/internal/main/print_help.js",
"lib/internal/main/prof_process.js",
"lib/internal/main/repl.js",
"lib/internal/main/run_main_module.js",
"lib/internal/main/single_executable_application.js",
"lib/internal/main/test_runner.js",
"lib/internal/main/watch_mode.js",
"lib/internal/main/worker_thread.js",
"lib/internal/mime.js",
"lib/internal/modules/cjs/helpers.js",
"lib/internal/modules/cjs/loader.js",
"lib/internal/modules/esm/assert.js",
"lib/internal/modules/esm/create_dynamic_module.js",
"lib/internal/modules/esm/fetch_module.js",
"lib/internal/modules/esm/formats.js",
"lib/internal/modules/esm/get_format.js",
"lib/internal/modules/esm/handle_process_exit.js",
"lib/internal/modules/esm/initialize_import_meta.js",
"lib/internal/modules/esm/load.js",
"lib/internal/modules/esm/loader.js",
"lib/internal/modules/esm/module_job.js",
"lib/internal/modules/esm/module_map.js",
"lib/internal/modules/esm/package_config.js",
"lib/internal/modules/esm/resolve.js",
"lib/internal/modules/esm/translators.js",
"lib/internal/modules/esm/utils.js",
"lib/internal/modules/package_json_reader.js",
"lib/internal/modules/run_main.js",
"lib/internal/net.js",
"lib/internal/options.js",
"lib/internal/per_context/domexception.js",
"lib/internal/per_context/messageport.js",
"lib/internal/per_context/primordials.js",
"lib/internal/perf/event_loop_delay.js",
"lib/internal/perf/event_loop_utilization.js",
"lib/internal/perf/nodetiming.js",
"lib/internal/perf/observe.js",
"lib/internal/perf/performance.js",
"lib/internal/perf/performance_entry.js",
"lib/internal/perf/resource_timing.js",
"lib/internal/perf/timerify.js",
"lib/internal/perf/usertiming.js",
"lib/internal/perf/utils.js",
"lib/internal/policy/manifest.js",
"lib/internal/policy/sri.js",
"lib/internal/priority_queue.js",
"lib/internal/process/esm_loader.js",
"lib/internal/process/execution.js",
"lib/internal/process/per_thread.js",
"lib/internal/process/policy.js",
"lib/internal/process/pre_execution.js",
"lib/internal/process/promises.js",
"lib/internal/process/report.js",
"lib/internal/process/signal.js",
"lib/internal/process/task_queues.js",
"lib/internal/process/warning.js",
"lib/internal/process/worker_thread_only.js",
"lib/internal/promise_hooks.js",
"lib/internal/querystring.js",
"lib/internal/readline/callbacks.js",
"lib/internal/readline/emitKeypressEvents.js",
"lib/internal/readline/interface.js",
"lib/internal/readline/promises.js",
"lib/internal/readline/utils.js",
"lib/internal/repl.js",
"lib/internal/repl/await.js",
"lib/internal/repl/history.js",
"lib/internal/repl/utils.js",
"lib/internal/socket_list.js",
"lib/internal/socketaddress.js",
"lib/internal/source_map/prepare_stack_trace.js",
"lib/internal/source_map/source_map.js",
"lib/internal/source_map/source_map_cache.js",
"lib/internal/stream_base_commons.js",
"lib/internal/streams/add-abort-signal.js",
"lib/internal/streams/buffer_list.js",
"lib/internal/streams/compose.js",
"lib/internal/streams/destroy.js",
"lib/internal/streams/duplex.js",
"lib/internal/streams/duplexify.js",
"lib/internal/streams/end-of-stream.js",
"lib/internal/streams/from.js",
"lib/internal/streams/lazy_transform.js",
"lib/internal/streams/legacy.js",
"lib/internal/streams/operators.js",
"lib/internal/streams/passthrough.js",
"lib/internal/streams/pipeline.js",
"lib/internal/streams/readable.js",
"lib/internal/streams/state.js",
"lib/internal/streams/transform.js",
"lib/internal/streams/utils.js",
"lib/internal/streams/writable.js",
"lib/internal/structured_clone.js",
"lib/internal/test/binding.js",
"lib/internal/test/transfer.js",
"lib/internal/test_runner/coverage.js",
"lib/internal/test_runner/harness.js",
"lib/internal/test_runner/mock.js",
"lib/internal/test_runner/reporter/dot.js",
"lib/internal/test_runner/reporter/spec.js",
"lib/internal/test_runner/reporter/tap.js",
"lib/internal/test_runner/reporter/v8-serializer.js",
"lib/internal/test_runner/runner.js",
"lib/internal/test_runner/test.js",
"lib/internal/test_runner/tests_stream.js",
"lib/internal/test_runner/utils.js",
"lib/internal/timers.js",
"lib/internal/tls/secure-context.js",
"lib/internal/tls/secure-pair.js",
"lib/internal/trace_events_async_hooks.js",
"lib/internal/tty.js",
"lib/internal/url.js",
"lib/internal/util.js",
"lib/internal/util/colors.js",
"lib/internal/util/comparisons.js",
"lib/internal/util/debuglog.js",
"lib/internal/util/inspect.js",
"lib/internal/util/inspector.js",
"lib/internal/util/iterable_weak_map.js",
"lib/internal/util/parse_args/parse_args.js",
"lib/internal/util/parse_args/utils.js",
"lib/internal/util/types.js",
"lib/internal/v8/startup_snapshot.js",
"lib/internal/v8_prof_polyfill.js",
"lib/internal/v8_prof_processor.js",
"lib/internal/validators.js",
"lib/internal/vm.js",
"lib/internal/vm/module.js",
"lib/internal/wasm_web_api.js",
"lib/internal/watch_mode/files_watcher.js",
"lib/internal/watchdog.js",
"lib/internal/webidl.js",
"lib/internal/webstreams/adapters.js",
"lib/internal/webstreams/compression.js",
"lib/internal/webstreams/encoding.js",
"lib/internal/webstreams/queuingstrategies.js",
"lib/internal/webstreams/readablestream.js",
"lib/internal/webstreams/transfer.js",
"lib/internal/webstreams/transformstream.js",
"lib/internal/webstreams/util.js",
"lib/internal/webstreams/writablestream.js",
"lib/internal/worker.js",
"lib/internal/worker/io.js",
"lib/internal/worker/js_transferable.js",
"lib/module.js",
"lib/net.js",
"lib/os.js",
"lib/path.js",
"lib/path/posix.js",
"lib/path/win32.js",
"lib/perf_hooks.js",
"lib/process.js",
"lib/punycode.js",
"lib/querystring.js",
"lib/readline.js",
"lib/readline/promises.js",
"lib/repl.js",
"lib/stream.js",
"lib/stream/consumers.js",
"lib/stream/promises.js",
"lib/stream/web.js",
"lib/string_decoder.js",
"lib/sys.js",
"lib/test.js",
"lib/test/reporters.js",
"lib/timers.js",
"lib/timers/promises.js",
"lib/tls.js",
"lib/trace_events.js",
"lib/tty.js",
"lib/url.js",
"lib/util.js",
"lib/util/types.js",
"lib/v8.js",
"lib/vm.js",
"lib/wasi.js",
"lib/worker_threads.js",
"lib/zlib.js"
],
"node_module_version": 119,
"node_no_browser_globals": "false",
"node_prefix": "\\usr\\local",
"node_release_urlbase": "",
"node_shared": "false",
"node_shared_brotli": "false",
"node_shared_cares": "false",
"node_shared_http_parser": "false",
"node_shared_libuv": "false",
"node_shared_nghttp2": "false",
"node_shared_nghttp3": "false",
"node_shared_ngtcp2": "false",
"node_shared_openssl": "false",
"node_shared_zlib": "false",
"node_tag": "",
"node_target_type": "executable",
"node_use_bundled_v8": "true",
"node_use_dtrace": "false",
"node_use_etw": "true",
"node_use_node_code_cache": "true",
"node_use_node_snapshot": "true",
"node_use_openssl": "true",
"node_use_v8_platform": "true",
"node_with_ltcg": "true",
"node_without_node_options": "false",
"openssl_is_fips": "false",
"openssl_no_asm": 1,
"openssl_quic": "true",
"ossfuzz": "false",
"shlib_suffix": "so.108",
"single_executable_application": "true",
"target_arch": "x64",
"using_electron_config_gypi": 1,
"v8_enable_31bit_smis_on_64bit_arch": 1,
"v8_enable_gdbjit": 0,
"v8_enable_hugepage": 0,
"v8_enable_i18n_support": 1,
"v8_enable_inspector": 1,
"v8_enable_javascript_promise_hooks": 1,
"v8_enable_lite_mode": 0,
"v8_enable_object_print": 1,
"v8_enable_pointer_compression": 1,
"v8_enable_sandbox": 1,
"v8_enable_shared_ro_heap": 0,
"v8_enable_short_builtin_calls": 1,
"v8_enable_webassembly": 1,
"v8_no_strict_aliasing": 1,
"v8_optimized_debug": 1,
"v8_promise_internal_field_count": 1,
"v8_random_seed": 0,
"v8_trace_maps": 0,
"v8_use_siphash": 1,
"want_separate_host_toolset": 0,
"nodedir": "/home/erik/.electron-gyp/28.3.3",
"standalone_static_library": 1,
"runtime": "electron",
"target": "28.3.3",
"build_from_source": "true",
"userconfig": "/home/erik/.npmrc",
"cache": "/home/erik/.npm",
"local_prefix": "/home/erik/Dokumente/PackControl",
"globalconfig": "/etc/npmrc",
"init_module": "/home/erik/.npm-init.js",
"npm_version": "11.7.0",
"prefix": "/usr",
"user_agent": "npm/11.7.0 node/v25.2.1 linux x64 workspaces/false",
"node_gyp": "/usr/lib/node_modules/node-gyp/bin/node-gyp.js",
"global_prefix": "/usr"
}
}

View File

@@ -0,0 +1 @@
/usr/bin/python3

38
node_modules/@serialport/bindings-cpp/dist/darwin.d.ts generated vendored Normal file
View File

@@ -0,0 +1,38 @@
import { BindingPortInterface } from '.';
import { BindingInterface, OpenOptions, PortStatus, SetOptions, UpdateOptions } from '@serialport/bindings-interface';
import { Poller } from './poller';
export interface DarwinOpenOptions extends OpenOptions {
/** Defaults to none */
parity?: 'none' | 'even' | 'odd';
/** see [`man termios`](http://linux.die.net/man/3/termios) defaults to 1 */
vmin?: number;
/** see [`man termios`](http://linux.die.net/man/3/termios) defaults to 0 */
vtime?: number;
}
export type DarwinBindingInterface = BindingInterface<DarwinPortBinding, DarwinOpenOptions>;
export declare const DarwinBinding: DarwinBindingInterface;
/**
* The Darwin binding layer for OSX
*/
export declare class DarwinPortBinding implements BindingPortInterface {
readonly openOptions: Required<DarwinOpenOptions>;
readonly poller: Poller;
private writeOperation;
fd: null | number;
constructor(fd: number, options: Required<DarwinOpenOptions>);
get isOpen(): boolean;
close(): Promise<void>;
read(buffer: Buffer, offset: number, length: number): Promise<{
buffer: Buffer;
bytesRead: number;
}>;
write(buffer: Buffer): Promise<void>;
update(options: UpdateOptions): Promise<void>;
set(options: SetOptions): Promise<void>;
get(): Promise<PortStatus>;
getBaudRate(): Promise<{
baudRate: number;
}>;
flush(): Promise<void>;
drain(): Promise<void>;
}

148
node_modules/@serialport/bindings-cpp/dist/darwin.js generated vendored Normal file
View File

@@ -0,0 +1,148 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DarwinPortBinding = exports.DarwinBinding = void 0;
const debug_1 = __importDefault(require("debug"));
const load_bindings_1 = require("./load-bindings");
const poller_1 = require("./poller");
const unix_read_1 = require("./unix-read");
const unix_write_1 = require("./unix-write");
const debug = (0, debug_1.default)('serialport/bindings-cpp');
exports.DarwinBinding = {
list() {
debug('list');
return (0, load_bindings_1.asyncList)();
},
async open(options) {
if (!options || typeof options !== 'object' || Array.isArray(options)) {
throw new TypeError('"options" is not an object');
}
if (!options.path) {
throw new TypeError('"path" is not a valid port');
}
if (!options.baudRate) {
throw new TypeError('"baudRate" is not a valid baudRate');
}
debug('open');
const openOptions = Object.assign({ vmin: 1, vtime: 0, dataBits: 8, lock: true, stopBits: 1, parity: 'none', rtscts: false, xon: false, xoff: false, xany: false, hupcl: true }, options);
const fd = await (0, load_bindings_1.asyncOpen)(openOptions.path, openOptions);
return new DarwinPortBinding(fd, openOptions);
},
};
/**
* The Darwin binding layer for OSX
*/
class DarwinPortBinding {
constructor(fd, options) {
this.fd = fd;
this.openOptions = options;
this.poller = new poller_1.Poller(fd);
this.writeOperation = null;
}
get isOpen() {
return this.fd !== null;
}
async close() {
debug('close');
if (!this.isOpen) {
throw new Error('Port is not open');
}
const fd = this.fd;
this.poller.stop();
this.poller.destroy();
this.fd = null;
await (0, load_bindings_1.asyncClose)(fd);
}
async read(buffer, offset, length) {
if (!Buffer.isBuffer(buffer)) {
throw new TypeError('"buffer" is not a Buffer');
}
if (typeof offset !== 'number' || isNaN(offset)) {
throw new TypeError(`"offset" is not an integer got "${isNaN(offset) ? 'NaN' : typeof offset}"`);
}
if (typeof length !== 'number' || isNaN(length)) {
throw new TypeError(`"length" is not an integer got "${isNaN(length) ? 'NaN' : typeof length}"`);
}
debug('read');
if (buffer.length < offset + length) {
throw new Error('buffer is too small');
}
if (!this.isOpen) {
throw new Error('Port is not open');
}
return (0, unix_read_1.unixRead)({ binding: this, buffer, offset, length });
}
async write(buffer) {
if (!Buffer.isBuffer(buffer)) {
throw new TypeError('"buffer" is not a Buffer');
}
debug('write', buffer.length, 'bytes');
if (!this.isOpen) {
debug('write', 'error port is not open');
throw new Error('Port is not open');
}
this.writeOperation = (async () => {
if (buffer.length === 0) {
return;
}
await (0, unix_write_1.unixWrite)({ binding: this, buffer });
this.writeOperation = null;
})();
return this.writeOperation;
}
async update(options) {
if (!options || typeof options !== 'object' || Array.isArray(options)) {
throw TypeError('"options" is not an object');
}
if (typeof options.baudRate !== 'number') {
throw new TypeError('"options.baudRate" is not a number');
}
debug('update');
if (!this.isOpen) {
throw new Error('Port is not open');
}
await (0, load_bindings_1.asyncUpdate)(this.fd, options);
}
async set(options) {
if (!options || typeof options !== 'object' || Array.isArray(options)) {
throw new TypeError('"options" is not an object');
}
debug('set', options);
if (!this.isOpen) {
throw new Error('Port is not open');
}
await (0, load_bindings_1.asyncSet)(this.fd, options);
}
async get() {
debug('get');
if (!this.isOpen) {
throw new Error('Port is not open');
}
return (0, load_bindings_1.asyncGet)(this.fd);
}
async getBaudRate() {
debug('getBaudRate');
if (!this.isOpen) {
throw new Error('Port is not open');
}
throw new Error('getBaudRate is not implemented on darwin');
}
async flush() {
debug('flush');
if (!this.isOpen) {
throw new Error('Port is not open');
}
await (0, load_bindings_1.asyncFlush)(this.fd);
}
async drain() {
debug('drain');
if (!this.isOpen) {
throw new Error('Port is not open');
}
await this.writeOperation;
await (0, load_bindings_1.asyncDrain)(this.fd);
}
}
exports.DarwinPortBinding = DarwinPortBinding;

View File

@@ -0,0 +1,7 @@
import { BindingsErrorInterface } from '@serialport/bindings-interface';
export declare class BindingsError extends Error implements BindingsErrorInterface {
canceled: boolean;
constructor(message: string, { canceled }?: {
canceled?: boolean | undefined;
});
}

10
node_modules/@serialport/bindings-cpp/dist/errors.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BindingsError = void 0;
class BindingsError extends Error {
constructor(message, { canceled = false } = {}) {
super(message);
this.canceled = canceled;
}
}
exports.BindingsError = BindingsError;

13
node_modules/@serialport/bindings-cpp/dist/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
import { DarwinBindingInterface } from './darwin';
import { LinuxBindingInterface } from './linux';
import { WindowsBindingInterface } from './win32';
export * from '@serialport/bindings-interface';
export * from './darwin';
export * from './linux';
export * from './win32';
export * from './errors';
export type AutoDetectTypes = DarwinBindingInterface | WindowsBindingInterface | LinuxBindingInterface;
/**
* This is an auto detected binding for your current platform
*/
export declare function autoDetect(): AutoDetectTypes;

47
node_modules/@serialport/bindings-cpp/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.autoDetect = autoDetect;
/* eslint-disable @typescript-eslint/no-var-requires */
const debug_1 = __importDefault(require("debug"));
const darwin_1 = require("./darwin");
const linux_1 = require("./linux");
const win32_1 = require("./win32");
const debug = (0, debug_1.default)('serialport/bindings-cpp');
__exportStar(require("@serialport/bindings-interface"), exports);
__exportStar(require("./darwin"), exports);
__exportStar(require("./linux"), exports);
__exportStar(require("./win32"), exports);
__exportStar(require("./errors"), exports);
/**
* This is an auto detected binding for your current platform
*/
function autoDetect() {
switch (process.platform) {
case 'win32':
debug('loading WindowsBinding');
return win32_1.WindowsBinding;
case 'darwin':
debug('loading DarwinBinding');
return darwin_1.DarwinBinding;
default:
debug('loading LinuxBinding');
return linux_1.LinuxBinding;
}
}

View File

@@ -0,0 +1,3 @@
import { spawn } from 'child_process';
import { PortInfo } from '@serialport/bindings-interface';
export declare function linuxList(spawnCmd?: typeof spawn): Promise<PortInfo[]>;

View File

@@ -0,0 +1,114 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.linuxList = linuxList;
const child_process_1 = require("child_process");
const parser_readline_1 = require("@serialport/parser-readline");
// get only serial port names
function checkPathOfDevice(path) {
return /(tty(S|WCH|ACM|USB|AMA|MFD|O|XRUSB)|rfcomm)/.test(path) && path;
}
function propName(name) {
return {
DEVNAME: 'path',
ID_VENDOR_ENC: 'manufacturer',
ID_SERIAL_SHORT: 'serialNumber',
ID_VENDOR_ID: 'vendorId',
ID_MODEL_ID: 'productId',
DEVLINKS: 'pnpId',
/**
* Workaround for systemd defect
* see https://github.com/serialport/bindings-cpp/issues/115
*/
ID_USB_VENDOR_ENC: 'manufacturer',
ID_USB_SERIAL_SHORT: 'serialNumber',
ID_USB_VENDOR_ID: 'vendorId',
ID_USB_MODEL_ID: 'productId',
// End of workaround
}[name.toUpperCase()];
}
function decodeHexEscape(str) {
return str.replace(/\\x([a-fA-F0-9]{2})/g, (a, b) => {
return String.fromCharCode(parseInt(b, 16));
});
}
function propVal(name, val) {
if (name === 'pnpId') {
const match = val.match(/\/by-id\/([^\s]+)/);
return (match === null || match === void 0 ? void 0 : match[1]) || undefined;
}
if (name === 'manufacturer') {
return decodeHexEscape(val);
}
if (/^0x/.test(val)) {
return val.substr(2);
}
return val;
}
function linuxList(spawnCmd = child_process_1.spawn) {
const ports = [];
const udevadm = spawnCmd('udevadm', ['info', '-e']);
const lines = udevadm.stdout.pipe(new parser_readline_1.ReadlineParser());
let skipPort = false;
let port = {
path: '',
manufacturer: undefined,
serialNumber: undefined,
pnpId: undefined,
locationId: undefined,
vendorId: undefined,
productId: undefined,
};
lines.on('data', (line) => {
const lineType = line.slice(0, 1);
const data = line.slice(3);
// new port entry
if (lineType === 'P') {
port = {
path: '',
manufacturer: undefined,
serialNumber: undefined,
pnpId: undefined,
locationId: undefined,
vendorId: undefined,
productId: undefined,
};
skipPort = false;
return;
}
if (skipPort) {
return;
}
// Check dev name and save port if it matches flag to skip the rest of the data if not
if (lineType === 'N') {
if (checkPathOfDevice(data)) {
ports.push(port);
}
else {
skipPort = true;
}
return;
}
// parse data about each port
if (lineType === 'E') {
const keyValue = data.match(/^(.+)=(.*)/);
if (!keyValue) {
return;
}
const key = propName(keyValue[1]);
if (!key) {
return;
}
port[key] = propVal(key, keyValue[2]);
}
});
return new Promise((resolve, reject) => {
udevadm.on('close', (code) => {
if (code) {
reject(new Error(`Error listing ports udevadm exited with error code: ${code}`));
}
});
udevadm.on('error', reject);
lines.on('error', reject);
lines.on('finish', () => resolve(ports));
});
}

45
node_modules/@serialport/bindings-cpp/dist/linux.d.ts generated vendored Normal file
View File

@@ -0,0 +1,45 @@
import { Poller } from './poller';
import { BindingInterface, OpenOptions, PortStatus, SetOptions, UpdateOptions } from '@serialport/bindings-interface';
import { BindingPortInterface } from '.';
export interface LinuxOpenOptions extends OpenOptions {
/** Defaults to none */
parity?: 'none' | 'even' | 'odd';
/** see [`man termios`](http://linux.die.net/man/3/termios) defaults to 1 */
vmin?: number;
/** see [`man termios`](http://linux.die.net/man/3/termios) defaults to 0 */
vtime?: number;
}
export interface LinuxPortStatus extends PortStatus {
lowLatency: boolean;
}
export interface LinuxSetOptions extends SetOptions {
/** Low latency mode */
lowLatency?: boolean;
}
export type LinuxBindingInterface = BindingInterface<LinuxPortBinding, LinuxOpenOptions>;
export declare const LinuxBinding: LinuxBindingInterface;
/**
* The linux binding layer
*/
export declare class LinuxPortBinding implements BindingPortInterface {
readonly openOptions: Required<LinuxOpenOptions>;
readonly poller: Poller;
private writeOperation;
fd: number | null;
constructor(fd: number, openOptions: Required<LinuxOpenOptions>);
get isOpen(): boolean;
close(): Promise<void>;
read(buffer: Buffer, offset: number, length: number): Promise<{
buffer: Buffer;
bytesRead: number;
}>;
write(buffer: Buffer): Promise<void>;
update(options: UpdateOptions): Promise<void>;
set(options: LinuxSetOptions): Promise<void>;
get(): Promise<LinuxPortStatus>;
getBaudRate(): Promise<{
baudRate: number;
}>;
flush(): Promise<void>;
drain(): Promise<void>;
}

150
node_modules/@serialport/bindings-cpp/dist/linux.js generated vendored Normal file
View File

@@ -0,0 +1,150 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LinuxPortBinding = exports.LinuxBinding = void 0;
const debug_1 = __importDefault(require("debug"));
const linux_list_1 = require("./linux-list");
const poller_1 = require("./poller");
const unix_read_1 = require("./unix-read");
const unix_write_1 = require("./unix-write");
const load_bindings_1 = require("./load-bindings");
const debug = (0, debug_1.default)('serialport/bindings-cpp');
exports.LinuxBinding = {
list() {
debug('list');
return (0, linux_list_1.linuxList)();
},
async open(options) {
if (!options || typeof options !== 'object' || Array.isArray(options)) {
throw new TypeError('"options" is not an object');
}
if (!options.path) {
throw new TypeError('"path" is not a valid port');
}
if (!options.baudRate) {
throw new TypeError('"baudRate" is not a valid baudRate');
}
debug('open');
const openOptions = Object.assign({ vmin: 1, vtime: 0, dataBits: 8, lock: true, stopBits: 1, parity: 'none', rtscts: false, xon: false, xoff: false, xany: false, hupcl: true }, options);
const fd = await (0, load_bindings_1.asyncOpen)(openOptions.path, openOptions);
this.fd = fd;
return new LinuxPortBinding(fd, openOptions);
},
};
/**
* The linux binding layer
*/
class LinuxPortBinding {
constructor(fd, openOptions) {
this.fd = fd;
this.openOptions = openOptions;
this.poller = new poller_1.Poller(fd);
this.writeOperation = null;
}
get isOpen() {
return this.fd !== null;
}
async close() {
debug('close');
if (!this.isOpen) {
throw new Error('Port is not open');
}
const fd = this.fd;
this.poller.stop();
this.poller.destroy();
this.fd = null;
await (0, load_bindings_1.asyncClose)(fd);
}
async read(buffer, offset, length) {
if (!Buffer.isBuffer(buffer)) {
throw new TypeError('"buffer" is not a Buffer');
}
if (typeof offset !== 'number' || isNaN(offset)) {
throw new TypeError(`"offset" is not an integer got "${isNaN(offset) ? 'NaN' : typeof offset}"`);
}
if (typeof length !== 'number' || isNaN(length)) {
throw new TypeError(`"length" is not an integer got "${isNaN(length) ? 'NaN' : typeof length}"`);
}
debug('read');
if (buffer.length < offset + length) {
throw new Error('buffer is too small');
}
if (!this.isOpen) {
throw new Error('Port is not open');
}
return (0, unix_read_1.unixRead)({ binding: this, buffer, offset, length });
}
async write(buffer) {
if (!Buffer.isBuffer(buffer)) {
throw new TypeError('"buffer" is not a Buffer');
}
debug('write', buffer.length, 'bytes');
if (!this.isOpen) {
debug('write', 'error port is not open');
throw new Error('Port is not open');
}
this.writeOperation = (async () => {
if (buffer.length === 0) {
return;
}
await (0, unix_write_1.unixWrite)({ binding: this, buffer });
this.writeOperation = null;
})();
return this.writeOperation;
}
async update(options) {
if (!options || typeof options !== 'object' || Array.isArray(options)) {
throw TypeError('"options" is not an object');
}
if (typeof options.baudRate !== 'number') {
throw new TypeError('"options.baudRate" is not a number');
}
debug('update');
if (!this.isOpen) {
throw new Error('Port is not open');
}
await (0, load_bindings_1.asyncUpdate)(this.fd, options);
}
async set(options) {
if (!options || typeof options !== 'object' || Array.isArray(options)) {
throw new TypeError('"options" is not an object');
}
debug('set');
if (!this.isOpen) {
throw new Error('Port is not open');
}
await (0, load_bindings_1.asyncSet)(this.fd, options);
}
async get() {
debug('get');
if (!this.isOpen) {
throw new Error('Port is not open');
}
return (0, load_bindings_1.asyncGet)(this.fd);
}
async getBaudRate() {
debug('getBaudRate');
if (!this.isOpen) {
throw new Error('Port is not open');
}
return (0, load_bindings_1.asyncGetBaudRate)(this.fd);
}
async flush() {
debug('flush');
if (!this.isOpen) {
throw new Error('Port is not open');
}
await (0, load_bindings_1.asyncFlush)(this.fd);
}
async drain() {
debug('drain');
if (!this.isOpen) {
throw new Error('Port is not open');
}
await this.writeOperation;
await (0, load_bindings_1.asyncDrain)(this.fd);
}
}
exports.LinuxPortBinding = LinuxPortBinding;

View File

@@ -0,0 +1,11 @@
export declare const asyncClose: Function;
export declare const asyncDrain: Function;
export declare const asyncFlush: Function;
export declare const asyncGet: Function;
export declare const asyncGetBaudRate: Function;
export declare const asyncList: Function;
export declare const asyncOpen: Function;
export declare const asyncSet: Function;
export declare const asyncUpdate: Function;
export declare const asyncRead: Function;
export declare const asyncWrite: Function;

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.asyncWrite = exports.asyncRead = exports.asyncUpdate = exports.asyncSet = exports.asyncOpen = exports.asyncList = exports.asyncGetBaudRate = exports.asyncGet = exports.asyncFlush = exports.asyncDrain = exports.asyncClose = void 0;
const util_1 = require("util");
const serialport_bindings_1 = require("./serialport-bindings");
exports.asyncClose = serialport_bindings_1.binding.close ? (0, util_1.promisify)(serialport_bindings_1.binding.close) : async () => { throw new Error('"binding.close" Method not implemented'); };
exports.asyncDrain = serialport_bindings_1.binding.drain ? (0, util_1.promisify)(serialport_bindings_1.binding.drain) : async () => { throw new Error('"binding.drain" Method not implemented'); };
exports.asyncFlush = serialport_bindings_1.binding.flush ? (0, util_1.promisify)(serialport_bindings_1.binding.flush) : async () => { throw new Error('"binding.flush" Method not implemented'); };
exports.asyncGet = serialport_bindings_1.binding.get ? (0, util_1.promisify)(serialport_bindings_1.binding.get) : async () => { throw new Error('"binding.get" Method not implemented'); };
exports.asyncGetBaudRate = serialport_bindings_1.binding.getBaudRate ? (0, util_1.promisify)(serialport_bindings_1.binding.getBaudRate) : async () => { throw new Error('"binding.getBaudRate" Method not implemented'); };
exports.asyncList = serialport_bindings_1.binding.list ? (0, util_1.promisify)(serialport_bindings_1.binding.list) : async () => { throw new Error('"binding.list" Method not implemented'); };
exports.asyncOpen = serialport_bindings_1.binding.open ? (0, util_1.promisify)(serialport_bindings_1.binding.open) : async () => { throw new Error('"binding.open" Method not implemented'); };
exports.asyncSet = serialport_bindings_1.binding.set ? (0, util_1.promisify)(serialport_bindings_1.binding.set) : async () => { throw new Error('"binding.set" Method not implemented'); };
exports.asyncUpdate = serialport_bindings_1.binding.update ? (0, util_1.promisify)(serialport_bindings_1.binding.update) : async () => { throw new Error('"binding.update" Method not implemented'); };
exports.asyncRead = serialport_bindings_1.binding.read ? (0, util_1.promisify)(serialport_bindings_1.binding.read) : async () => { throw new Error('"binding.read" Method not implemented'); };
exports.asyncWrite = serialport_bindings_1.binding.write ? (0, util_1.promisify)(serialport_bindings_1.binding.write) : async () => { throw new Error('"binding.write" Method not implemented'); };

39
node_modules/@serialport/bindings-cpp/dist/poller.d.ts generated vendored Normal file
View File

@@ -0,0 +1,39 @@
import { EventEmitter } from 'events';
interface PollerClass {
new (fd: number, cb: (err: Error, flag: number) => void): PollerInstance;
}
interface PollerInstance {
poll(flag: number): void;
stop(): void;
destroy(): void;
}
export declare const EVENTS: {
UV_READABLE: number;
UV_WRITABLE: number;
UV_DISCONNECT: number;
};
/**
* Polls unix systems for readable or writable states of a file or serialport
*/
export declare class Poller extends EventEmitter {
poller: PollerInstance;
constructor(fd: number, FDPoller?: PollerClass);
/**
* Wait for the next event to occur
* @param {string} event ('readable'|'writable'|'disconnect')
* @returns {Poller} returns itself
*/
once(event: 'readable' | 'writable' | 'disconnect', callback: (err: null | Error) => void): this;
/**
* Ask the bindings to listen for an event, it is recommend to use `.once()` for easy use
* @param {EVENTS} eventFlag polls for an event or group of events based upon a flag.
*/
poll(eventFlag?: number): void;
/**
* Stop listening for events and cancel all outstanding listening with an error
*/
stop(): void;
destroy(): void;
emitCanceled(): void;
}
export {};

103
node_modules/@serialport/bindings-cpp/dist/poller.js generated vendored Normal file
View File

@@ -0,0 +1,103 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Poller = exports.EVENTS = void 0;
const debug_1 = __importDefault(require("debug"));
const events_1 = require("events");
const errors_1 = require("./errors");
const serialport_bindings_1 = require("./serialport-bindings");
const { Poller: PollerBindings } = serialport_bindings_1.binding;
const logger = (0, debug_1.default)('serialport/bindings-cpp/poller');
exports.EVENTS = {
UV_READABLE: 0b0001,
UV_WRITABLE: 0b0010,
UV_DISCONNECT: 0b0100,
};
function handleEvent(error, eventFlag) {
if (error) {
logger('error', error);
this.emit('readable', error);
this.emit('writable', error);
this.emit('disconnect', error);
return;
}
if (eventFlag & exports.EVENTS.UV_READABLE) {
logger('received "readable"');
this.emit('readable', null);
}
if (eventFlag & exports.EVENTS.UV_WRITABLE) {
logger('received "writable"');
this.emit('writable', null);
}
if (eventFlag & exports.EVENTS.UV_DISCONNECT) {
logger('received "disconnect"');
this.emit('disconnect', null);
}
}
/**
* Polls unix systems for readable or writable states of a file or serialport
*/
class Poller extends events_1.EventEmitter {
constructor(fd, FDPoller = PollerBindings) {
logger('Creating poller');
super();
this.poller = new FDPoller(fd, handleEvent.bind(this));
}
/**
* Wait for the next event to occur
* @param {string} event ('readable'|'writable'|'disconnect')
* @returns {Poller} returns itself
*/
once(event, callback) {
switch (event) {
case 'readable':
this.poll(exports.EVENTS.UV_READABLE);
break;
case 'writable':
this.poll(exports.EVENTS.UV_WRITABLE);
break;
case 'disconnect':
this.poll(exports.EVENTS.UV_DISCONNECT);
break;
}
return super.once(event, callback);
}
/**
* Ask the bindings to listen for an event, it is recommend to use `.once()` for easy use
* @param {EVENTS} eventFlag polls for an event or group of events based upon a flag.
*/
poll(eventFlag = 0) {
if (eventFlag & exports.EVENTS.UV_READABLE) {
logger('Polling for "readable"');
}
if (eventFlag & exports.EVENTS.UV_WRITABLE) {
logger('Polling for "writable"');
}
if (eventFlag & exports.EVENTS.UV_DISCONNECT) {
logger('Polling for "disconnect"');
}
this.poller.poll(eventFlag);
}
/**
* Stop listening for events and cancel all outstanding listening with an error
*/
stop() {
logger('Stopping poller');
this.poller.stop();
this.emitCanceled();
}
destroy() {
logger('Destroying poller');
this.poller.destroy();
this.emitCanceled();
}
emitCanceled() {
const err = new errors_1.BindingsError('Canceled', { canceled: true });
this.emit('readable', err);
this.emit('writable', err);
this.emit('disconnect', err);
}
}
exports.Poller = Poller;

View File

@@ -0,0 +1 @@
export declare const binding: any;

View File

@@ -0,0 +1,10 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.binding = void 0;
const path_1 = require("path");
const node_gyp_build_1 = __importDefault(require("node-gyp-build"));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
exports.binding = (0, node_gyp_build_1.default)((0, path_1.join)(__dirname, '../'));

View File

@@ -0,0 +1,16 @@
import { read as fsRead } from 'fs';
import { LinuxPortBinding } from './linux';
import { DarwinPortBinding } from './darwin';
declare const readAsync: typeof fsRead.__promisify__;
interface UnixReadOptions {
binding: LinuxPortBinding | DarwinPortBinding;
buffer: Buffer;
offset: number;
length: number;
fsReadAsync?: typeof readAsync;
}
export declare const unixRead: ({ binding, buffer, offset, length, fsReadAsync, }: UnixReadOptions) => Promise<{
buffer: Buffer;
bytesRead: number;
}>;
export {};

View File

@@ -0,0 +1,55 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.unixRead = void 0;
const util_1 = require("util");
const fs_1 = require("fs");
const errors_1 = require("./errors");
const debug_1 = __importDefault(require("debug"));
const logger = (0, debug_1.default)('serialport/bindings-cpp/unixRead');
const readAsync = (0, util_1.promisify)(fs_1.read);
const readable = (binding) => {
return new Promise((resolve, reject) => {
if (!binding.poller) {
throw new Error('No poller on bindings');
}
binding.poller.once('readable', err => (err ? reject(err) : resolve()));
});
};
const unixRead = async ({ binding, buffer, offset, length, fsReadAsync = readAsync, }) => {
logger('Starting read');
if (!binding.isOpen || !binding.fd) {
throw new errors_1.BindingsError('Port is not open', { canceled: true });
}
try {
const { bytesRead } = await fsReadAsync(binding.fd, buffer, offset, length, null);
if (bytesRead === 0) {
return (0, exports.unixRead)({ binding, buffer, offset, length, fsReadAsync });
}
logger('Finished read', bytesRead, 'bytes');
return { bytesRead, buffer };
}
catch (err) {
logger('read error', err);
if (err.code === 'EAGAIN' || err.code === 'EWOULDBLOCK' || err.code === 'EINTR') {
if (!binding.isOpen) {
throw new errors_1.BindingsError('Port is not open', { canceled: true });
}
logger('waiting for readable because of code:', err.code);
await readable(binding);
return (0, exports.unixRead)({ binding, buffer, offset, length, fsReadAsync });
}
const disconnectError = err.code === 'EBADF' || // Bad file number means we got closed
err.code === 'ENXIO' || // No such device or address probably usb disconnect
err.code === 'UNKNOWN' ||
err.errno === -1; // generic error
if (disconnectError) {
err.disconnect = true;
logger('disconnecting', err);
}
throw err;
}
};
exports.unixRead = unixRead;

View File

@@ -0,0 +1,12 @@
import { write } from 'fs';
import { LinuxPortBinding } from './linux';
import { DarwinPortBinding } from './darwin';
declare const writeAsync: typeof write.__promisify__;
interface UnixWriteOptions {
binding: LinuxPortBinding | DarwinPortBinding;
buffer: Buffer;
offset?: number;
fsWriteAsync?: typeof writeAsync;
}
export declare const unixWrite: ({ binding, buffer, offset, fsWriteAsync }: UnixWriteOptions) => Promise<void>;
export {};

View File

@@ -0,0 +1,56 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.unixWrite = void 0;
const fs_1 = require("fs");
const debug_1 = __importDefault(require("debug"));
const util_1 = require("util");
const logger = (0, debug_1.default)('serialport/bindings-cpp/unixWrite');
const writeAsync = (0, util_1.promisify)(fs_1.write);
const writable = (binding) => {
return new Promise((resolve, reject) => {
binding.poller.once('writable', err => (err ? reject(err) : resolve()));
});
};
const unixWrite = async ({ binding, buffer, offset = 0, fsWriteAsync = writeAsync }) => {
const bytesToWrite = buffer.length - offset;
logger('Starting write', buffer.length, 'bytes offset', offset, 'bytesToWrite', bytesToWrite);
if (!binding.isOpen || !binding.fd) {
throw new Error('Port is not open');
}
try {
const { bytesWritten } = await fsWriteAsync(binding.fd, buffer, offset, bytesToWrite);
logger('write returned: wrote', bytesWritten, 'bytes');
if (bytesWritten + offset < buffer.length) {
if (!binding.isOpen) {
throw new Error('Port is not open');
}
return (0, exports.unixWrite)({ binding, buffer, offset: bytesWritten + offset, fsWriteAsync });
}
logger('Finished writing', bytesWritten + offset, 'bytes');
}
catch (err) {
logger('write errored', err);
if (err.code === 'EAGAIN' || err.code === 'EWOULDBLOCK' || err.code === 'EINTR') {
if (!binding.isOpen) {
throw new Error('Port is not open');
}
logger('waiting for writable because of code:', err.code);
await writable(binding);
return (0, exports.unixWrite)({ binding, buffer, offset, fsWriteAsync });
}
const disconnectError = err.code === 'EBADF' || // Bad file number means we got closed
err.code === 'ENXIO' || // No such device or address probably usb disconnect
err.code === 'UNKNOWN' ||
err.errno === -1; // generic error
if (disconnectError) {
err.disconnect = true;
logger('disconnecting', err);
}
logger('error', err);
throw err;
}
};
exports.unixWrite = unixWrite;

View File

@@ -0,0 +1 @@
export declare const serialNumParser: (pnpId?: string) => string | null;

View File

@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.serialNumParser = void 0;
const PARSERS = [/USB\\(?:.+)\\(.+)/, /FTDIBUS\\(?:.+)\+(.+?)A?\\.+/];
const serialNumParser = (pnpId) => {
if (!pnpId) {
return null;
}
for (const parser of PARSERS) {
const sn = pnpId.match(parser);
if (sn) {
return sn[1];
}
}
return null;
};
exports.serialNumParser = serialNumParser;

34
node_modules/@serialport/bindings-cpp/dist/win32.d.ts generated vendored Normal file
View File

@@ -0,0 +1,34 @@
import { BindingPortInterface } from '.';
import { BindingInterface, OpenOptions, PortStatus, SetOptions, UpdateOptions } from '@serialport/bindings-interface';
export interface WindowsOpenOptions extends OpenOptions {
/** Device parity defaults to none */
parity?: 'none' | 'even' | 'odd' | 'mark' | 'space';
/** RTS mode defaults to handshake */
rtsMode?: 'handshake' | 'enable' | 'toggle';
}
export type WindowsBindingInterface = BindingInterface<WindowsPortBinding, WindowsOpenOptions>;
export declare const WindowsBinding: WindowsBindingInterface;
/**
* The Windows binding layer
*/
export declare class WindowsPortBinding implements BindingPortInterface {
fd: null | number;
writeOperation: Promise<void> | null;
openOptions: Required<OpenOptions>;
constructor(fd: number, options: Required<OpenOptions>);
get isOpen(): boolean;
close(): Promise<void>;
read(buffer: Buffer, offset: number, length: number): Promise<{
buffer: Buffer;
bytesRead: number;
}>;
write(buffer: Buffer): Promise<void>;
update(options: UpdateOptions): Promise<void>;
set(options: SetOptions): Promise<void>;
get(): Promise<PortStatus>;
getBaudRate(): Promise<{
baudRate: number;
}>;
flush(): Promise<void>;
drain(): Promise<void>;
}

162
node_modules/@serialport/bindings-cpp/dist/win32.js generated vendored Normal file
View File

@@ -0,0 +1,162 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WindowsPortBinding = exports.WindowsBinding = void 0;
const debug_1 = __importDefault(require("debug"));
const _1 = require(".");
const load_bindings_1 = require("./load-bindings");
const win32_sn_parser_1 = require("./win32-sn-parser");
const debug = (0, debug_1.default)('serialport/bindings-cpp');
exports.WindowsBinding = {
async list() {
const ports = await (0, load_bindings_1.asyncList)();
// Grab the serial number from the pnp id
return ports.map(port => {
if (port.pnpId && !port.serialNumber) {
const serialNumber = (0, win32_sn_parser_1.serialNumParser)(port.pnpId);
if (serialNumber) {
return Object.assign(Object.assign({}, port), { serialNumber });
}
}
return port;
});
},
async open(options) {
if (!options || typeof options !== 'object' || Array.isArray(options)) {
throw new TypeError('"options" is not an object');
}
if (!options.path) {
throw new TypeError('"path" is not a valid port');
}
if (!options.baudRate) {
throw new TypeError('"baudRate" is not a valid baudRate');
}
debug('open');
const openOptions = Object.assign({ dataBits: 8, lock: true, stopBits: 1, parity: 'none', rtscts: false, rtsMode: 'handshake', xon: false, xoff: false, xany: false, hupcl: true }, options);
const fd = await (0, load_bindings_1.asyncOpen)(openOptions.path, openOptions);
return new WindowsPortBinding(fd, openOptions);
},
};
/**
* The Windows binding layer
*/
class WindowsPortBinding {
constructor(fd, options) {
this.fd = fd;
this.openOptions = options;
this.writeOperation = null;
}
get isOpen() {
return this.fd !== null;
}
async close() {
debug('close');
if (!this.isOpen) {
throw new Error('Port is not open');
}
const fd = this.fd;
this.fd = null;
await (0, load_bindings_1.asyncClose)(fd);
}
async read(buffer, offset, length) {
if (!Buffer.isBuffer(buffer)) {
throw new TypeError('"buffer" is not a Buffer');
}
if (typeof offset !== 'number' || isNaN(offset)) {
throw new TypeError(`"offset" is not an integer got "${isNaN(offset) ? 'NaN' : typeof offset}"`);
}
if (typeof length !== 'number' || isNaN(length)) {
throw new TypeError(`"length" is not an integer got "${isNaN(length) ? 'NaN' : typeof length}"`);
}
debug('read');
if (buffer.length < offset + length) {
throw new Error('buffer is too small');
}
if (!this.isOpen) {
throw new Error('Port is not open');
}
try {
const bytesRead = await (0, load_bindings_1.asyncRead)(this.fd, buffer, offset, length);
return { bytesRead, buffer };
}
catch (err) {
if (!this.isOpen) {
throw new _1.BindingsError(err.message, { canceled: true });
}
throw err;
}
}
async write(buffer) {
if (!Buffer.isBuffer(buffer)) {
throw new TypeError('"buffer" is not a Buffer');
}
debug('write', buffer.length, 'bytes');
if (!this.isOpen) {
debug('write', 'error port is not open');
throw new Error('Port is not open');
}
this.writeOperation = (async () => {
if (buffer.length === 0) {
return;
}
await (0, load_bindings_1.asyncWrite)(this.fd, buffer);
this.writeOperation = null;
})();
return this.writeOperation;
}
async update(options) {
if (!options || typeof options !== 'object' || Array.isArray(options)) {
throw TypeError('"options" is not an object');
}
if (typeof options.baudRate !== 'number') {
throw new TypeError('"options.baudRate" is not a number');
}
debug('update');
if (!this.isOpen) {
throw new Error('Port is not open');
}
await (0, load_bindings_1.asyncUpdate)(this.fd, options);
}
async set(options) {
if (!options || typeof options !== 'object' || Array.isArray(options)) {
throw new TypeError('"options" is not an object');
}
debug('set', options);
if (!this.isOpen) {
throw new Error('Port is not open');
}
await (0, load_bindings_1.asyncSet)(this.fd, options);
}
async get() {
debug('get');
if (!this.isOpen) {
throw new Error('Port is not open');
}
return (0, load_bindings_1.asyncGet)(this.fd);
}
async getBaudRate() {
debug('getBaudRate');
if (!this.isOpen) {
throw new Error('Port is not open');
}
return (0, load_bindings_1.asyncGetBaudRate)(this.fd);
}
async flush() {
debug('flush');
if (!this.isOpen) {
throw new Error('Port is not open');
}
await (0, load_bindings_1.asyncFlush)(this.fd);
}
async drain() {
debug('drain');
if (!this.isOpen) {
throw new Error('Port is not open');
}
await this.writeOperation;
await (0, load_bindings_1.asyncDrain)(this.fd);
}
}
exports.WindowsPortBinding = WindowsPortBinding;

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright 2010 Christopher Williams. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

View File

@@ -0,0 +1,3 @@
# @serialport/parser-delimiter
See our api docs https://serialport.io/docs/api-parser-delimiter

View File

@@ -0,0 +1,23 @@
/// <reference types="node" />
/// <reference types="node" />
import { Transform, TransformCallback, TransformOptions } from 'stream';
export interface DelimiterOptions extends TransformOptions {
/** The delimiter on which to split incoming data. */
delimiter: string | Buffer | number[];
/** Should the delimiter be included at the end of data. Defaults to `false` */
includeDelimiter?: boolean;
}
/**
* A transform stream that emits data each time a byte sequence is received.
* @extends Transform
*
* To use the `Delimiter` parser, provide a delimiter as a string, buffer, or array of bytes. Runs in O(n) time.
*/
export declare class DelimiterParser extends Transform {
includeDelimiter: boolean;
delimiter: Buffer;
buffer: Buffer;
constructor({ delimiter, includeDelimiter, ...options }: DelimiterOptions);
_transform(chunk: Buffer, encoding: BufferEncoding, cb: TransformCallback): void;
_flush(cb: TransformCallback): void;
}

View File

@@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DelimiterParser = void 0;
const stream_1 = require("stream");
/**
* A transform stream that emits data each time a byte sequence is received.
* @extends Transform
*
* To use the `Delimiter` parser, provide a delimiter as a string, buffer, or array of bytes. Runs in O(n) time.
*/
class DelimiterParser extends stream_1.Transform {
includeDelimiter;
delimiter;
buffer;
constructor({ delimiter, includeDelimiter = false, ...options }) {
super(options);
if (delimiter === undefined) {
throw new TypeError('"delimiter" is not a bufferable object');
}
if (delimiter.length === 0) {
throw new TypeError('"delimiter" has a 0 or undefined length');
}
this.includeDelimiter = includeDelimiter;
this.delimiter = Buffer.from(delimiter);
this.buffer = Buffer.alloc(0);
}
_transform(chunk, encoding, cb) {
let data = Buffer.concat([this.buffer, chunk]);
let position;
while ((position = data.indexOf(this.delimiter)) !== -1) {
this.push(data.slice(0, position + (this.includeDelimiter ? this.delimiter.length : 0)));
data = data.slice(position + this.delimiter.length);
}
this.buffer = data;
cb();
}
_flush(cb) {
this.push(this.buffer);
this.buffer = Buffer.alloc(0);
cb();
}
}
exports.DelimiterParser = DelimiterParser;

View File

@@ -0,0 +1,25 @@
{
"name": "@serialport/parser-delimiter",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"version": "12.0.0",
"engines": {
"node": ">=12.0.0"
},
"publishConfig": {
"access": "public"
},
"license": "MIT",
"scripts": {
"build": "tsc --build tsconfig-build.json"
},
"repository": {
"type": "git",
"url": "git://github.com/serialport/node-serialport.git"
},
"funding": "https://opencollective.com/serialport/donate",
"devDependencies": {
"typescript": "5.2.2"
},
"gitHead": "f7e7bd53f9578a26c4f44cc1949fef396dc064c7"
}

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright 2010 Christopher Williams. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

View File

@@ -0,0 +1,3 @@
# @serialport/parser-readline
See our api docs See our api docs https://serialport.io/docs/api-parser-readline

View File

@@ -0,0 +1,19 @@
/// <reference types="node" />
/// <reference types="node" />
import { DelimiterParser } from '@serialport/parser-delimiter';
import { TransformOptions } from 'stream';
export interface ReadlineOptions extends TransformOptions {
/** delimiter to use defaults to \n */
delimiter?: string | Buffer | number[];
/** include the delimiter at the end of the packet defaults to false */
includeDelimiter?: boolean;
/** Defaults to utf8 */
encoding?: BufferEncoding;
}
/**
* A transform stream that emits data after a newline delimiter is received.
* @summary To use the `Readline` parser, provide a delimiter (defaults to `\n`). Data is emitted as string controllable by the `encoding` option (defaults to `utf8`).
*/
export declare class ReadlineParser extends DelimiterParser {
constructor(options?: ReadlineOptions);
}

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReadlineParser = void 0;
const parser_delimiter_1 = require("@serialport/parser-delimiter");
/**
* A transform stream that emits data after a newline delimiter is received.
* @summary To use the `Readline` parser, provide a delimiter (defaults to `\n`). Data is emitted as string controllable by the `encoding` option (defaults to `utf8`).
*/
class ReadlineParser extends parser_delimiter_1.DelimiterParser {
constructor(options) {
const opts = {
delimiter: Buffer.from('\n', 'utf8'),
encoding: 'utf8',
...options,
};
if (typeof opts.delimiter === 'string') {
opts.delimiter = Buffer.from(opts.delimiter, opts.encoding);
}
super(opts);
}
}
exports.ReadlineParser = ReadlineParser;

View File

@@ -0,0 +1,28 @@
{
"name": "@serialport/parser-readline",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"version": "12.0.0",
"dependencies": {
"@serialport/parser-delimiter": "12.0.0"
},
"engines": {
"node": ">=12.0.0"
},
"publishConfig": {
"access": "public"
},
"license": "MIT",
"scripts": {
"build": "tsc --build tsconfig-build.json"
},
"repository": {
"type": "git",
"url": "git://github.com/serialport/node-serialport.git"
},
"funding": "https://opencollective.com/serialport/donate",
"devDependencies": {
"typescript": "5.2.2"
},
"gitHead": "f7e7bd53f9578a26c4f44cc1949fef396dc064c7"
}

View File

@@ -0,0 +1,20 @@
(The MIT License)
Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
Copyright (c) 2018-2021 Josh Junon
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the 'Software'), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,481 @@
# debug
[![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers)
[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors)
<img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png">
A tiny JavaScript debugging utility modelled after Node.js core's debugging
technique. Works in Node.js and web browsers.
## Installation
```bash
$ npm install debug
```
## Usage
`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
Example [_app.js_](./examples/node/app.js):
```js
var debug = require('debug')('http')
, http = require('http')
, name = 'My App';
// fake app
debug('booting %o', name);
http.createServer(function(req, res){
debug(req.method + ' ' + req.url);
res.end('hello\n');
}).listen(3000, function(){
debug('listening');
});
// fake worker of some kind
require('./worker');
```
Example [_worker.js_](./examples/node/worker.js):
```js
var a = require('debug')('worker:a')
, b = require('debug')('worker:b');
function work() {
a('doing lots of uninteresting work');
setTimeout(work, Math.random() * 1000);
}
work();
function workb() {
b('doing some work');
setTimeout(workb, Math.random() * 2000);
}
workb();
```
The `DEBUG` environment variable is then used to enable these based on space or
comma-delimited names.
Here are some examples:
<img width="647" alt="screen shot 2017-08-08 at 12 53 04 pm" src="https://user-images.githubusercontent.com/71256/29091703-a6302cdc-7c38-11e7-8304-7c0b3bc600cd.png">
<img width="647" alt="screen shot 2017-08-08 at 12 53 38 pm" src="https://user-images.githubusercontent.com/71256/29091700-a62a6888-7c38-11e7-800b-db911291ca2b.png">
<img width="647" alt="screen shot 2017-08-08 at 12 53 25 pm" src="https://user-images.githubusercontent.com/71256/29091701-a62ea114-7c38-11e7-826a-2692bedca740.png">
#### Windows command prompt notes
##### CMD
On Windows the environment variable is set using the `set` command.
```cmd
set DEBUG=*,-not_this
```
Example:
```cmd
set DEBUG=* & node app.js
```
##### PowerShell (VS Code default)
PowerShell uses different syntax to set environment variables.
```cmd
$env:DEBUG = "*,-not_this"
```
Example:
```cmd
$env:DEBUG='app';node app.js
```
Then, run the program to be debugged as usual.
npm script example:
```js
"windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js",
```
## Namespace Colors
Every debug instance has a color generated for it based on its namespace name.
This helps when visually parsing the debug output to identify which debug instance
a debug line belongs to.
#### Node.js
In Node.js, colors are enabled when stderr is a TTY. You also _should_ install
the [`supports-color`](https://npmjs.org/supports-color) module alongside debug,
otherwise debug will only use a small handful of basic colors.
<img width="521" src="https://user-images.githubusercontent.com/71256/29092181-47f6a9e6-7c3a-11e7-9a14-1928d8a711cd.png">
#### Web Browser
Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
option. These are WebKit web inspectors, Firefox ([since version
31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
and the Firebug plugin for Firefox (any version).
<img width="524" src="https://user-images.githubusercontent.com/71256/29092033-b65f9f2e-7c39-11e7-8e32-f6f0d8e865c1.png">
## Millisecond diff
When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
<img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png">
When stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below:
<img width="647" src="https://user-images.githubusercontent.com/71256/29091956-6bd78372-7c39-11e7-8c55-c948396d6edd.png">
## Conventions
If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". If you append a "*" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable. You can then use it for normal output as well as debug output.
## Wildcards
The `*` character may be used as a wildcard. Suppose for example your library has
debuggers named "connect:bodyParser", "connect:compress", "connect:session",
instead of listing all three with
`DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do
`DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
You can also exclude specific debuggers by prefixing them with a "-" character.
For example, `DEBUG=*,-connect:*` would include all debuggers except those
starting with "connect:".
## Environment Variables
When running through Node.js, you can set a few environment variables that will
change the behavior of the debug logging:
| Name | Purpose |
|-----------|-------------------------------------------------|
| `DEBUG` | Enables/disables specific debugging namespaces. |
| `DEBUG_HIDE_DATE` | Hide date from debug output (non-TTY). |
| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
| `DEBUG_DEPTH` | Object inspection depth. |
| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
__Note:__ The environment variables beginning with `DEBUG_` end up being
converted into an Options object that gets used with `%o`/`%O` formatters.
See the Node.js documentation for
[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
for the complete list.
## Formatters
Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting.
Below are the officially supported formatters:
| Formatter | Representation |
|-----------|----------------|
| `%O` | Pretty-print an Object on multiple lines. |
| `%o` | Pretty-print an Object all on a single line. |
| `%s` | String. |
| `%d` | Number (both integer and float). |
| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
| `%%` | Single percent sign ('%'). This does not consume an argument. |
### Custom formatters
You can add custom formatters by extending the `debug.formatters` object.
For example, if you wanted to add support for rendering a Buffer as hex with
`%h`, you could do something like:
```js
const createDebug = require('debug')
createDebug.formatters.h = (v) => {
return v.toString('hex')
}
// …elsewhere
const debug = createDebug('foo')
debug('this is hex: %h', new Buffer('hello world'))
// foo this is hex: 68656c6c6f20776f726c6421 +0ms
```
## Browser Support
You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
if you don't want to build it yourself.
Debug's enable state is currently persisted by `localStorage`.
Consider the situation shown below where you have `worker:a` and `worker:b`,
and wish to debug both. You can enable this using `localStorage.debug`:
```js
localStorage.debug = 'worker:*'
```
And then refresh the page.
```js
a = debug('worker:a');
b = debug('worker:b');
setInterval(function(){
a('doing some work');
}, 1000);
setInterval(function(){
b('doing some work');
}, 1200);
```
In Chromium-based web browsers (e.g. Brave, Chrome, and Electron), the JavaScript console will—by default—only show messages logged by `debug` if the "Verbose" log level is _enabled_.
<img width="647" src="https://user-images.githubusercontent.com/7143133/152083257-29034707-c42c-4959-8add-3cee850e6fcf.png">
## Output streams
By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
Example [_stdout.js_](./examples/node/stdout.js):
```js
var debug = require('debug');
var error = debug('app:error');
// by default stderr is used
error('goes to stderr!');
var log = debug('app:log');
// set this namespace to log via console.log
log.log = console.log.bind(console); // don't forget to bind to console!
log('goes to stdout');
error('still goes to stderr!');
// set all output to go via console.info
// overrides all per-namespace log settings
debug.log = console.info.bind(console);
error('now goes to stdout via console.info');
log('still goes to stdout, but via console.info now');
```
## Extend
You can simply extend debugger
```js
const log = require('debug')('auth');
//creates new debug instance with extended namespace
const logSign = log.extend('sign');
const logLogin = log.extend('login');
log('hello'); // auth hello
logSign('hello'); //auth:sign hello
logLogin('hello'); //auth:login hello
```
## Set dynamically
You can also enable debug dynamically by calling the `enable()` method :
```js
let debug = require('debug');
console.log(1, debug.enabled('test'));
debug.enable('test');
console.log(2, debug.enabled('test'));
debug.disable();
console.log(3, debug.enabled('test'));
```
print :
```
1 false
2 true
3 false
```
Usage :
`enable(namespaces)`
`namespaces` can include modes separated by a colon and wildcards.
Note that calling `enable()` completely overrides previously set DEBUG variable :
```
$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))'
=> false
```
`disable()`
Will disable all namespaces. The functions returns the namespaces currently
enabled (and skipped). This can be useful if you want to disable debugging
temporarily without knowing what was enabled to begin with.
For example:
```js
let debug = require('debug');
debug.enable('foo:*,-foo:bar');
let namespaces = debug.disable();
debug.enable(namespaces);
```
Note: There is no guarantee that the string will be identical to the initial
enable string, but semantically they will be identical.
## Checking whether a debug target is enabled
After you've created a debug instance, you can determine whether or not it is
enabled by checking the `enabled` property:
```javascript
const debug = require('debug')('http');
if (debug.enabled) {
// do stuff...
}
```
You can also manually toggle this property to force the debug instance to be
enabled or disabled.
## Usage in child processes
Due to the way `debug` detects if the output is a TTY or not, colors are not shown in child processes when `stderr` is piped. A solution is to pass the `DEBUG_COLORS=1` environment variable to the child process.
For example:
```javascript
worker = fork(WORKER_WRAP_PATH, [workerPath], {
stdio: [
/* stdin: */ 0,
/* stdout: */ 'pipe',
/* stderr: */ 'pipe',
'ipc',
],
env: Object.assign({}, process.env, {
DEBUG_COLORS: 1 // without this settings, colors won't be shown
}),
});
worker.stderr.pipe(process.stderr, { end: false });
```
## Authors
- TJ Holowaychuk
- Nathan Rajlich
- Andrew Rhyne
- Josh Junon
## Backers
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
<a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a>
## Sponsors
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
<a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a>
## License
(The MIT License)
Copyright (c) 2014-2017 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
Copyright (c) 2018-2021 Josh Junon
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,65 @@
{
"name": "debug",
"version": "4.4.0",
"repository": {
"type": "git",
"url": "git://github.com/debug-js/debug.git"
},
"description": "Lightweight debugging utility for Node.js and the browser",
"keywords": [
"debug",
"log",
"debugger"
],
"files": [
"src",
"LICENSE",
"README.md"
],
"author": "Josh Junon (https://github.com/qix-)",
"contributors": [
"TJ Holowaychuk <tj@vision-media.ca>",
"Nathan Rajlich <nathan@tootallnate.net> (http://n8.io)",
"Andrew Rhyne <rhyneandrew@gmail.com>"
],
"license": "MIT",
"scripts": {
"lint": "xo",
"test": "npm run test:node && npm run test:browser && npm run lint",
"test:node": "istanbul cover _mocha -- test.js test.node.js",
"test:browser": "karma start --single-run",
"test:coverage": "cat ./coverage/lcov.info | coveralls"
},
"dependencies": {
"ms": "^2.1.3"
},
"devDependencies": {
"brfs": "^2.0.1",
"browserify": "^16.2.3",
"coveralls": "^3.0.2",
"istanbul": "^0.4.5",
"karma": "^3.1.4",
"karma-browserify": "^6.0.0",
"karma-chrome-launcher": "^2.2.0",
"karma-mocha": "^1.3.0",
"mocha": "^5.2.0",
"mocha-lcov-reporter": "^1.2.0",
"sinon": "^14.0.0",
"xo": "^0.23.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
},
"main": "./src/index.js",
"browser": "./src/browser.js",
"engines": {
"node": ">=6.0"
},
"xo": {
"rules": {
"import/extensions": "off"
}
}
}

View File

@@ -0,0 +1,272 @@
/* eslint-env browser */
/**
* This is the web browser implementation of `debug()`.
*/
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = localstorage();
exports.destroy = (() => {
let warned = false;
return () => {
if (!warned) {
warned = true;
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
}
};
})();
/**
* Colors.
*/
exports.colors = [
'#0000CC',
'#0000FF',
'#0033CC',
'#0033FF',
'#0066CC',
'#0066FF',
'#0099CC',
'#0099FF',
'#00CC00',
'#00CC33',
'#00CC66',
'#00CC99',
'#00CCCC',
'#00CCFF',
'#3300CC',
'#3300FF',
'#3333CC',
'#3333FF',
'#3366CC',
'#3366FF',
'#3399CC',
'#3399FF',
'#33CC00',
'#33CC33',
'#33CC66',
'#33CC99',
'#33CCCC',
'#33CCFF',
'#6600CC',
'#6600FF',
'#6633CC',
'#6633FF',
'#66CC00',
'#66CC33',
'#9900CC',
'#9900FF',
'#9933CC',
'#9933FF',
'#99CC00',
'#99CC33',
'#CC0000',
'#CC0033',
'#CC0066',
'#CC0099',
'#CC00CC',
'#CC00FF',
'#CC3300',
'#CC3333',
'#CC3366',
'#CC3399',
'#CC33CC',
'#CC33FF',
'#CC6600',
'#CC6633',
'#CC9900',
'#CC9933',
'#CCCC00',
'#CCCC33',
'#FF0000',
'#FF0033',
'#FF0066',
'#FF0099',
'#FF00CC',
'#FF00FF',
'#FF3300',
'#FF3333',
'#FF3366',
'#FF3399',
'#FF33CC',
'#FF33FF',
'#FF6600',
'#FF6633',
'#FF9900',
'#FF9933',
'#FFCC00',
'#FFCC33'
];
/**
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
* and the Firebug extension (any Firefox version) are known
* to support "%c" CSS customizations.
*
* TODO: add a `localStorage` variable to explicitly enable/disable colors
*/
// eslint-disable-next-line complexity
function useColors() {
// NB: In an Electron preload script, document will be defined but not fully
// initialized. Since we know we're in Chrome, we'll just detect this case
// explicitly
if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
return true;
}
// Internet Explorer and Edge do not support colors.
if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
return false;
}
let m;
// Is webkit? http://stackoverflow.com/a/16459606/376773
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
// eslint-disable-next-line no-return-assign
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
// Is firebug? http://stackoverflow.com/a/398120/376773
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
// Is firefox >= v31?
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
(typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31) ||
// Double check webkit in userAgent just in case we are in a worker
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
}
/**
* Colorize log arguments if enabled.
*
* @api public
*/
function formatArgs(args) {
args[0] = (this.useColors ? '%c' : '') +
this.namespace +
(this.useColors ? ' %c' : ' ') +
args[0] +
(this.useColors ? '%c ' : ' ') +
'+' + module.exports.humanize(this.diff);
if (!this.useColors) {
return;
}
const c = 'color: ' + this.color;
args.splice(1, 0, c, 'color: inherit');
// The final "%c" is somewhat tricky, because there could be other
// arguments passed either before or after the %c, so we need to
// figure out the correct index to insert the CSS into
let index = 0;
let lastC = 0;
args[0].replace(/%[a-zA-Z%]/g, match => {
if (match === '%%') {
return;
}
index++;
if (match === '%c') {
// We only are interested in the *last* %c
// (the user may have provided their own)
lastC = index;
}
});
args.splice(lastC, 0, c);
}
/**
* Invokes `console.debug()` when available.
* No-op when `console.debug` is not a "function".
* If `console.debug` is not available, falls back
* to `console.log`.
*
* @api public
*/
exports.log = console.debug || console.log || (() => {});
/**
* Save `namespaces`.
*
* @param {String} namespaces
* @api private
*/
function save(namespaces) {
try {
if (namespaces) {
exports.storage.setItem('debug', namespaces);
} else {
exports.storage.removeItem('debug');
}
} catch (error) {
// Swallow
// XXX (@Qix-) should we be logging these?
}
}
/**
* Load `namespaces`.
*
* @return {String} returns the previously persisted debug modes
* @api private
*/
function load() {
let r;
try {
r = exports.storage.getItem('debug');
} catch (error) {
// Swallow
// XXX (@Qix-) should we be logging these?
}
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
if (!r && typeof process !== 'undefined' && 'env' in process) {
r = process.env.DEBUG;
}
return r;
}
/**
* Localstorage attempts to return the localstorage.
*
* This is necessary because safari throws
* when a user disables cookies/localstorage
* and you attempt to access it.
*
* @return {LocalStorage}
* @api private
*/
function localstorage() {
try {
// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
// The Browser also has localStorage in the global context.
return localStorage;
} catch (error) {
// Swallow
// XXX (@Qix-) should we be logging these?
}
}
module.exports = require('./common')(exports);
const {formatters} = module.exports;
/**
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
*/
formatters.j = function (v) {
try {
return JSON.stringify(v);
} catch (error) {
return '[UnexpectedJSONParseError]: ' + error.message;
}
};

View File

@@ -0,0 +1,292 @@
/**
* This is the common logic for both the Node.js and web browser
* implementations of `debug()`.
*/
function setup(env) {
createDebug.debug = createDebug;
createDebug.default = createDebug;
createDebug.coerce = coerce;
createDebug.disable = disable;
createDebug.enable = enable;
createDebug.enabled = enabled;
createDebug.humanize = require('ms');
createDebug.destroy = destroy;
Object.keys(env).forEach(key => {
createDebug[key] = env[key];
});
/**
* The currently active debug mode names, and names to skip.
*/
createDebug.names = [];
createDebug.skips = [];
/**
* Map of special "%n" handling functions, for the debug "format" argument.
*
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
*/
createDebug.formatters = {};
/**
* Selects a color for a debug namespace
* @param {String} namespace The namespace string for the debug instance to be colored
* @return {Number|String} An ANSI color code for the given namespace
* @api private
*/
function selectColor(namespace) {
let hash = 0;
for (let i = 0; i < namespace.length; i++) {
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
hash |= 0; // Convert to 32bit integer
}
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
}
createDebug.selectColor = selectColor;
/**
* Create a debugger with the given `namespace`.
*
* @param {String} namespace
* @return {Function}
* @api public
*/
function createDebug(namespace) {
let prevTime;
let enableOverride = null;
let namespacesCache;
let enabledCache;
function debug(...args) {
// Disabled?
if (!debug.enabled) {
return;
}
const self = debug;
// Set `diff` timestamp
const curr = Number(new Date());
const ms = curr - (prevTime || curr);
self.diff = ms;
self.prev = prevTime;
self.curr = curr;
prevTime = curr;
args[0] = createDebug.coerce(args[0]);
if (typeof args[0] !== 'string') {
// Anything else let's inspect with %O
args.unshift('%O');
}
// Apply any `formatters` transformations
let index = 0;
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
// If we encounter an escaped % then don't increase the array index
if (match === '%%') {
return '%';
}
index++;
const formatter = createDebug.formatters[format];
if (typeof formatter === 'function') {
const val = args[index];
match = formatter.call(self, val);
// Now we need to remove `args[index]` since it's inlined in the `format`
args.splice(index, 1);
index--;
}
return match;
});
// Apply env-specific formatting (colors, etc.)
createDebug.formatArgs.call(self, args);
const logFn = self.log || createDebug.log;
logFn.apply(self, args);
}
debug.namespace = namespace;
debug.useColors = createDebug.useColors();
debug.color = createDebug.selectColor(namespace);
debug.extend = extend;
debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.
Object.defineProperty(debug, 'enabled', {
enumerable: true,
configurable: false,
get: () => {
if (enableOverride !== null) {
return enableOverride;
}
if (namespacesCache !== createDebug.namespaces) {
namespacesCache = createDebug.namespaces;
enabledCache = createDebug.enabled(namespace);
}
return enabledCache;
},
set: v => {
enableOverride = v;
}
});
// Env-specific initialization logic for debug instances
if (typeof createDebug.init === 'function') {
createDebug.init(debug);
}
return debug;
}
function extend(namespace, delimiter) {
const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
newDebug.log = this.log;
return newDebug;
}
/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
*
* @param {String} namespaces
* @api public
*/
function enable(namespaces) {
createDebug.save(namespaces);
createDebug.namespaces = namespaces;
createDebug.names = [];
createDebug.skips = [];
const split = (typeof namespaces === 'string' ? namespaces : '')
.trim()
.replace(' ', ',')
.split(',')
.filter(Boolean);
for (const ns of split) {
if (ns[0] === '-') {
createDebug.skips.push(ns.slice(1));
} else {
createDebug.names.push(ns);
}
}
}
/**
* Checks if the given string matches a namespace template, honoring
* asterisks as wildcards.
*
* @param {String} search
* @param {String} template
* @return {Boolean}
*/
function matchesTemplate(search, template) {
let searchIndex = 0;
let templateIndex = 0;
let starIndex = -1;
let matchIndex = 0;
while (searchIndex < search.length) {
if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) {
// Match character or proceed with wildcard
if (template[templateIndex] === '*') {
starIndex = templateIndex;
matchIndex = searchIndex;
templateIndex++; // Skip the '*'
} else {
searchIndex++;
templateIndex++;
}
} else if (starIndex !== -1) { // eslint-disable-line no-negated-condition
// Backtrack to the last '*' and try to match more characters
templateIndex = starIndex + 1;
matchIndex++;
searchIndex = matchIndex;
} else {
return false; // No match
}
}
// Handle trailing '*' in template
while (templateIndex < template.length && template[templateIndex] === '*') {
templateIndex++;
}
return templateIndex === template.length;
}
/**
* Disable debug output.
*
* @return {String} namespaces
* @api public
*/
function disable() {
const namespaces = [
...createDebug.names,
...createDebug.skips.map(namespace => '-' + namespace)
].join(',');
createDebug.enable('');
return namespaces;
}
/**
* Returns true if the given mode name is enabled, false otherwise.
*
* @param {String} name
* @return {Boolean}
* @api public
*/
function enabled(name) {
for (const skip of createDebug.skips) {
if (matchesTemplate(name, skip)) {
return false;
}
}
for (const ns of createDebug.names) {
if (matchesTemplate(name, ns)) {
return true;
}
}
return false;
}
/**
* Coerce `val`.
*
* @param {Mixed} val
* @return {Mixed}
* @api private
*/
function coerce(val) {
if (val instanceof Error) {
return val.stack || val.message;
}
return val;
}
/**
* XXX DO NOT USE. This is a temporary stub function.
* XXX It WILL be removed in the next major release.
*/
function destroy() {
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
}
createDebug.enable(createDebug.load());
return createDebug;
}
module.exports = setup;

View File

@@ -0,0 +1,10 @@
/**
* Detect Electron renderer / nwjs process, which is node, but we should
* treat as a browser.
*/
if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
module.exports = require('./browser.js');
} else {
module.exports = require('./node.js');
}

View File

@@ -0,0 +1,263 @@
/**
* Module dependencies.
*/
const tty = require('tty');
const util = require('util');
/**
* This is the Node.js implementation of `debug()`.
*/
exports.init = init;
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.destroy = util.deprecate(
() => {},
'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'
);
/**
* Colors.
*/
exports.colors = [6, 2, 3, 4, 5, 1];
try {
// Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
// eslint-disable-next-line import/no-extraneous-dependencies
const supportsColor = require('supports-color');
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
exports.colors = [
20,
21,
26,
27,
32,
33,
38,
39,
40,
41,
42,
43,
44,
45,
56,
57,
62,
63,
68,
69,
74,
75,
76,
77,
78,
79,
80,
81,
92,
93,
98,
99,
112,
113,
128,
129,
134,
135,
148,
149,
160,
161,
162,
163,
164,
165,
166,
167,
168,
169,
170,
171,
172,
173,
178,
179,
184,
185,
196,
197,
198,
199,
200,
201,
202,
203,
204,
205,
206,
207,
208,
209,
214,
215,
220,
221
];
}
} catch (error) {
// Swallow - we only care if `supports-color` is available; it doesn't have to be.
}
/**
* Build up the default `inspectOpts` object from the environment variables.
*
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
*/
exports.inspectOpts = Object.keys(process.env).filter(key => {
return /^debug_/i.test(key);
}).reduce((obj, key) => {
// Camel-case
const prop = key
.substring(6)
.toLowerCase()
.replace(/_([a-z])/g, (_, k) => {
return k.toUpperCase();
});
// Coerce string value into JS value
let val = process.env[key];
if (/^(yes|on|true|enabled)$/i.test(val)) {
val = true;
} else if (/^(no|off|false|disabled)$/i.test(val)) {
val = false;
} else if (val === 'null') {
val = null;
} else {
val = Number(val);
}
obj[prop] = val;
return obj;
}, {});
/**
* Is stdout a TTY? Colored output is enabled when `true`.
*/
function useColors() {
return 'colors' in exports.inspectOpts ?
Boolean(exports.inspectOpts.colors) :
tty.isatty(process.stderr.fd);
}
/**
* Adds ANSI color escape codes if enabled.
*
* @api public
*/
function formatArgs(args) {
const {namespace: name, useColors} = this;
if (useColors) {
const c = this.color;
const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
const prefix = ` ${colorCode};1m${name} \u001B[0m`;
args[0] = prefix + args[0].split('\n').join('\n' + prefix);
args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m');
} else {
args[0] = getDate() + name + ' ' + args[0];
}
}
function getDate() {
if (exports.inspectOpts.hideDate) {
return '';
}
return new Date().toISOString() + ' ';
}
/**
* Invokes `util.formatWithOptions()` with the specified arguments and writes to stderr.
*/
function log(...args) {
return process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + '\n');
}
/**
* Save `namespaces`.
*
* @param {String} namespaces
* @api private
*/
function save(namespaces) {
if (namespaces) {
process.env.DEBUG = namespaces;
} else {
// If you set a process.env field to null or undefined, it gets cast to the
// string 'null' or 'undefined'. Just delete instead.
delete process.env.DEBUG;
}
}
/**
* Load `namespaces`.
*
* @return {String} returns the previously persisted debug modes
* @api private
*/
function load() {
return process.env.DEBUG;
}
/**
* Init logic for `debug` instances.
*
* Create a new `inspectOpts` object in case `useColors` is set
* differently for a particular `debug` instance.
*/
function init(debug) {
debug.inspectOpts = {};
const keys = Object.keys(exports.inspectOpts);
for (let i = 0; i < keys.length; i++) {
debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
}
}
module.exports = require('./common')(exports);
const {formatters} = module.exports;
/**
* Map %o to `util.inspect()`, all on a single line.
*/
formatters.o = function (v) {
this.inspectOpts.colors = this.useColors;
return util.inspect(v, this.inspectOpts)
.split('\n')
.map(str => str.trim())
.join(' ');
};
/**
* Map %O to `util.inspect()`, allowing multiple lines if needed.
*/
formatters.O = function (v) {
this.inspectOpts.colors = this.useColors;
return util.inspect(v, this.inspectOpts);
};

113
node_modules/@serialport/bindings-cpp/package.json generated vendored Normal file
View File

@@ -0,0 +1,113 @@
{
"name": "@serialport/bindings-cpp",
"description": "SerialPort Hardware bindings for node serialport written in c++",
"version": "13.0.0",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"keywords": [
"serialport-binding",
"COM",
"com port",
"hardware",
"iot",
"modem",
"serial port",
"serial",
"serialport",
"tty",
"UART"
],
"dependencies": {
"@serialport/bindings-interface": "1.2.2",
"@serialport/parser-readline": "12.0.0",
"debug": "4.4.0",
"node-addon-api": "8.3.0",
"node-gyp-build": "4.8.4"
},
"devDependencies": {
"@semantic-release/exec": "6.0.3",
"@serialport/binding-mock": "10.2.2",
"@types/chai": "5.0.1",
"@types/chai-subset": "1.3.5",
"@types/debug": "4.1.12",
"@types/mocha": "10.0.10",
"@types/node": "22.8.2",
"@typescript-eslint/eslint-plugin": "6.21.0",
"@typescript-eslint/parser": "6.21.0",
"cc": "3.0.1",
"chai": "5.1.2",
"chai-subset": "1.6.0",
"esbuild": "0.24.2",
"esbuild-register": "3.6.0",
"eslint": "8.57.1",
"mocha": "11.0.1",
"node-abi": "3.71.0",
"node-gyp": "11.0.0",
"nyc": "17.1.0",
"prebuildify": "6.0.1",
"prebuildify-cross": "5.1.1",
"semantic-release": "24.2.0",
"shx": "0.3.4",
"sinon": "19.0.2",
"typescript": "5.7.2"
},
"engines": {
"node": ">=18.0.0"
},
"scripts": {
"build": "rm -rf dist && tsc -p tsconfig-build.json",
"install": "node-gyp-build",
"prebuildify": "prebuildify --napi --target 20.0.0 --force --strip --verbose",
"prebuildify-cross": "prebuildify-cross --napi --target 20.0.0 --force --strip --verbose",
"rebuild": "node-gyp rebuild",
"format": "eslint lib test bin --fix",
"lint": "eslint lib test bin && cc --verbose",
"test": "nyc --reporter lcov --reporter text mocha",
"test:arduino": "TEST_PORT=$(./bin/find-arduino.ts) npm test",
"test:watch": "mocha -w",
"semantic-release": "semantic-release",
"typecheck": "tsc"
},
"publishConfig": {
"access": "public"
},
"license": "MIT",
"gypfile": true,
"cc": {
"filter": [
"legal/copyright",
"build/include"
],
"files": [
"src/*.cpp",
"src/*.h"
],
"linelength": "120"
},
"binary": {
"napi_versions": [
8
]
},
"repository": {
"type": "git",
"url": "https://github.com/serialport/bindings-cpp.git"
},
"funding": "https://opencollective.com/serialport/donate",
"changelog": {
"labels": {
"breaking": ":boom: BREAKING CHANGES :boom:",
"feature-request": "Features",
"bug": "Bug Fixes",
"docs": "Documentation",
"internal": "Chores"
}
},
"mocha": {
"bail": true,
"require": [
"esbuild-register"
],
"spec": "lib/**/*.test.*"
}
}

View File

@@ -0,0 +1,317 @@
#include "./darwin_list.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/serial/IOSerialKeys.h>
#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
#include <sys/ioctl.h>
#include <IOKit/serial/ioss.h>
#endif
#include <string>
#include <list>
uv_mutex_t list_mutex;
Boolean lockInitialised = FALSE;
Napi::Value List(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// callback
if (!info[0].IsFunction()) {
Napi::TypeError::New(env, "First argument must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function callback = info[0].As<Napi::Function>();
ListBaton* baton = new ListBaton(callback);
snprintf(baton->errorString, sizeof(baton->errorString), "");
baton->Queue();
return env.Undefined();
}
void setIfNotEmpty(Napi::Object item, std::string key, const char *value) {
Napi::Env env = item.Env();
Napi::String v8key = Napi::String::New(env, key);
if (strlen(value) > 0) {
(item).Set(v8key, Napi::String::New(env, value));
} else {
(item).Set(v8key, env.Undefined());
}
}
// Function prototypes
static kern_return_t FindModems(io_iterator_t *matchingServices);
static io_service_t GetUsbDevice(io_service_t service);
static stDeviceListItem* GetSerialDevices();
static kern_return_t FindModems(io_iterator_t *matchingServices) {
kern_return_t kernResult;
CFMutableDictionaryRef classesToMatch;
classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
if (classesToMatch != NULL) {
CFDictionarySetValue(classesToMatch,
CFSTR(kIOSerialBSDTypeKey),
CFSTR(kIOSerialBSDAllTypes));
}
kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, matchingServices);
return kernResult;
}
static io_service_t GetUsbDevice(io_service_t service) {
IOReturn status;
io_iterator_t iterator = 0;
io_service_t device = 0;
if (!service) {
return device;
}
status = IORegistryEntryCreateIterator(service,
kIOServicePlane,
(kIORegistryIterateParents | kIORegistryIterateRecursively),
&iterator);
if (status == kIOReturnSuccess) {
io_service_t currentService;
while ((currentService = IOIteratorNext(iterator)) && device == 0) {
io_name_t serviceName;
status = IORegistryEntryGetNameInPlane(currentService, kIOServicePlane, serviceName);
if (status == kIOReturnSuccess && IOObjectConformsTo(currentService, kIOUSBDeviceClassName)) {
device = currentService;
} else {
// Release the service object which is no longer needed
(void) IOObjectRelease(currentService);
}
}
// Release the iterator
(void) IOObjectRelease(iterator);
}
return device;
}
static void ExtractUsbInformation(stSerialDevice *serialDevice, IOUSBDeviceInterface **deviceInterface) {
kern_return_t kernResult;
UInt32 locationID;
kernResult = (*deviceInterface)->GetLocationID(deviceInterface, &locationID);
if (KERN_SUCCESS == kernResult) {
snprintf(serialDevice->locationId, sizeof(serialDevice->locationId), "%08x", locationID);
}
UInt16 vendorID;
kernResult = (*deviceInterface)->GetDeviceVendor(deviceInterface, &vendorID);
if (KERN_SUCCESS == kernResult) {
snprintf(serialDevice->vendorId, sizeof(serialDevice->vendorId), "%04x", vendorID);
}
UInt16 productID;
kernResult = (*deviceInterface)->GetDeviceProduct(deviceInterface, &productID);
if (KERN_SUCCESS == kernResult) {
snprintf(serialDevice->productId, sizeof(serialDevice->productId), "%04x", productID);
}
}
static stDeviceListItem* GetSerialDevices() {
char bsdPath[MAXPATHLEN];
io_iterator_t serialPortIterator;
FindModems(&serialPortIterator);
kern_return_t kernResult = KERN_FAILURE;
Boolean modemFound = false;
// Initialize the returned path
*bsdPath = '\0';
stDeviceListItem* devices = NULL;
stDeviceListItem* lastDevice = NULL;
int length = 0;
io_service_t modemService;
while ((modemService = IOIteratorNext(serialPortIterator))) {
CFTypeRef bsdPathAsCFString;
bsdPathAsCFString = IORegistryEntrySearchCFProperty(
modemService,
kIOServicePlane,
CFSTR(kIODialinDeviceKey),
kCFAllocatorDefault,
kIORegistryIterateRecursively);
if (bsdPathAsCFString) {
Boolean result;
// Convert the path from a CFString to a C (NUL-terminated)
result = CFStringGetCString((CFStringRef) bsdPathAsCFString,
bsdPath,
sizeof(bsdPath),
kCFStringEncodingUTF8);
CFRelease(bsdPathAsCFString);
if (result) {
stDeviceListItem *deviceListItem = reinterpret_cast<stDeviceListItem*>( malloc(sizeof(stDeviceListItem)));
stSerialDevice *serialDevice = &(deviceListItem->value);
snprintf(serialDevice->port, sizeof(serialDevice->port), "%s", bsdPath);
memset(serialDevice->locationId, 0, sizeof(serialDevice->locationId));
memset(serialDevice->vendorId, 0, sizeof(serialDevice->vendorId));
memset(serialDevice->productId, 0, sizeof(serialDevice->productId));
serialDevice->manufacturer[0] = '\0';
serialDevice->serialNumber[0] = '\0';
deviceListItem->next = NULL;
deviceListItem->length = &length;
if (devices == NULL) {
devices = deviceListItem;
} else {
lastDevice->next = deviceListItem;
}
lastDevice = deviceListItem;
length++;
modemFound = true;
kernResult = KERN_SUCCESS;
uv_mutex_lock(&list_mutex);
io_service_t device = GetUsbDevice(modemService);
if (device) {
CFStringRef manufacturerAsCFString = (CFStringRef) IORegistryEntryCreateCFProperty(device,
CFSTR(kUSBVendorString),
kCFAllocatorDefault,
0);
if (manufacturerAsCFString) {
Boolean result;
char manufacturer[MAXPATHLEN];
// Convert from a CFString to a C (NUL-terminated)
result = CFStringGetCString(manufacturerAsCFString,
manufacturer,
sizeof(manufacturer),
kCFStringEncodingUTF8);
if (result) {
snprintf(serialDevice->manufacturer, sizeof(serialDevice->manufacturer), "%s", manufacturer);
}
CFRelease(manufacturerAsCFString);
}
CFStringRef serialNumberAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty(device,
kIOServicePlane,
CFSTR(kUSBSerialNumberString),
kCFAllocatorDefault,
kIORegistryIterateRecursively);
if (serialNumberAsCFString) {
Boolean result;
char serialNumber[MAXPATHLEN];
// Convert from a CFString to a C (NUL-terminated)
result = CFStringGetCString(serialNumberAsCFString,
serialNumber,
sizeof(serialNumber),
kCFStringEncodingUTF8);
if (result) {
snprintf(serialDevice->serialNumber, sizeof(serialDevice->serialNumber), "%s", serialNumber);
}
CFRelease(serialNumberAsCFString);
}
IOCFPlugInInterface **plugInInterface = NULL;
SInt32 score;
HRESULT res;
IOUSBDeviceInterface **deviceInterface = NULL;
kernResult = IOCreatePlugInInterfaceForService(device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
&plugInInterface, &score);
if ((kIOReturnSuccess == kernResult) && plugInInterface) {
// Use the plugin interface to retrieve the device interface.
res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
reinterpret_cast<LPVOID*> (&deviceInterface));
// Now done with the plugin interface.
(*plugInInterface)->Release(plugInInterface);
if (!res && deviceInterface != NULL) {
// Extract the desired Information
ExtractUsbInformation(serialDevice, deviceInterface);
// Release the Interface
(*deviceInterface)->Release(deviceInterface);
}
}
// Release the device
(void) IOObjectRelease(device);
}
uv_mutex_unlock(&list_mutex);
}
}
// Release the io_service_t now that we are done with it.
(void) IOObjectRelease(modemService);
}
IOObjectRelease(serialPortIterator); // Release the iterator.
return devices;
}
void ListBaton::Execute() {
if (!lockInitialised) {
uv_mutex_init(&list_mutex);
lockInitialised = TRUE;
}
stDeviceListItem* devices = GetSerialDevices();
if (devices != NULL && *(devices->length) > 0) {
stDeviceListItem* next = devices;
for (int i = 0, len = *(devices->length); i < len; i++) {
stSerialDevice device = (* next).value;
ListResultItem* resultItem = new ListResultItem();
resultItem->path = device.port;
if (*device.locationId) {
resultItem->locationId = device.locationId;
}
if (*device.vendorId) {
resultItem->vendorId = device.vendorId;
}
if (*device.productId) {
resultItem->productId = device.productId;
}
if (*device.manufacturer) {
resultItem->manufacturer = device.manufacturer;
}
if (*device.serialNumber) {
resultItem->serialNumber = device.serialNumber;
}
results.push_back(resultItem);
stDeviceListItem* current = next;
if (next->next != NULL) {
next = next->next;
}
free(current);
}
}
}

View File

@@ -0,0 +1,68 @@
#ifndef PACKAGES_SERIALPORT_SRC_DARWIN_LIST_H_
#define PACKAGES_SERIALPORT_SRC_DARWIN_LIST_H_
#include <sys/param.h> // For MAXPATHLEN
#include <napi.h>
#include <uv.h>
#include <list>
#include <string>
#define ERROR_STRING_SIZE 1088
Napi::Value List(const Napi::CallbackInfo& info);
void setIfNotEmpty(Napi::Object item, std::string key, const char *value);
struct ListResultItem {
std::string path;
std::string manufacturer;
std::string serialNumber;
std::string pnpId;
std::string locationId;
std::string vendorId;
std::string productId;
};
struct ListBaton : public Napi::AsyncWorker {
ListBaton(Napi::Function& callback) : Napi::AsyncWorker(callback, "node-serialport:ListBaton"),
errorString() {}
std::list<ListResultItem*> results;
char errorString[ERROR_STRING_SIZE];
void Execute() override;
void OnOK() override {
Napi::Env env = Env();
Napi::HandleScope scope(env);
Napi::Array result = Napi::Array::New(env);
int i = 0;
for (std::list<ListResultItem*>::iterator it = results.begin(); it != results.end(); ++it, i++) {
Napi::Object item = Napi::Object::New(env);
setIfNotEmpty(item, "path", (*it)->path.c_str());
setIfNotEmpty(item, "manufacturer", (*it)->manufacturer.c_str());
setIfNotEmpty(item, "serialNumber", (*it)->serialNumber.c_str());
setIfNotEmpty(item, "pnpId", (*it)->pnpId.c_str());
setIfNotEmpty(item, "locationId", (*it)->locationId.c_str());
setIfNotEmpty(item, "vendorId", (*it)->vendorId.c_str());
setIfNotEmpty(item, "productId", (*it)->productId.c_str());
(result).Set(i, item);
}
Callback().Call({env.Null(), result});
}
};
typedef struct SerialDevice {
char port[MAXPATHLEN];
char locationId[MAXPATHLEN];
char vendorId[MAXPATHLEN];
char productId[MAXPATHLEN];
char manufacturer[MAXPATHLEN];
char serialNumber[MAXPATHLEN];
} stSerialDevice;
typedef struct DeviceListItem {
struct SerialDevice value;
struct DeviceListItem *next;
int* length;
} stDeviceListItem;
#endif // PACKAGES_SERIALPORT_SRC_DARWIN_LIST_H_

166
node_modules/@serialport/bindings-cpp/src/poller.cpp generated vendored Normal file
View File

@@ -0,0 +1,166 @@
#include <napi.h>
#include <uv.h>
#include "./poller.h"
Poller::Poller (const Napi::CallbackInfo &info) : Napi::ObjectWrap<Poller>(info)
{
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "First argument must be an int").ThrowAsJavaScriptException();
return;
}
this->fd = info[0].As<Napi::Number>().Int32Value();
// callback
if (!info[1].IsFunction()) {
Napi::TypeError::New(env, "Second argument must be a function").ThrowAsJavaScriptException();
return;
}
this->callback = Napi::Persistent(info[1].As<Napi::Function>());
this->poll_handle = new uv_poll_t();
memset(this->poll_handle, 0, sizeof(uv_poll_t));
poll_handle->data = this;
int status = uv_poll_init(uv_default_loop(), poll_handle, fd);
if (0 != status) {
Napi::Error::New(env, uv_strerror(status)).ThrowAsJavaScriptException();
return;
}
uv_poll_init_success = true;
}
Poller::~Poller() {
// if we call uv_poll_stop after uv_poll_init failed we segfault
if (uv_poll_init_success) {
uv_poll_stop(poll_handle);
uv_unref(reinterpret_cast<uv_handle_t*> (poll_handle));
uv_close(reinterpret_cast<uv_handle_t*> (poll_handle), Poller::onClose);
} else {
delete poll_handle;
}
return;
}
void Poller::onClose(uv_handle_t* poll_handle) {
// fprintf(stdout, "~Poller is closed\n");
delete poll_handle;
}
// Events can be UV_READABLE | UV_WRITABLE | UV_DISCONNECT
void Poller::poll(Napi::Env env, int events) {
Napi::HandleScope scope(env);
// fprintf(stdout, "Poller:poll for %d\n", events);
this->events = this->events | events;
int status = uv_poll_start(this->poll_handle, events, Poller::onData);
if (0 != status) {
Napi::Error::New(env, uv_strerror(status)).ThrowAsJavaScriptException();
}
return;
}
void Poller::stop(Napi::Env env) {
Napi::HandleScope scope(env);
int status = uv_poll_stop(this->poll_handle);
if (0 != status) {
Napi::Error::New(env, uv_strerror(status)).ThrowAsJavaScriptException();
}
return;
}
int Poller::_stop() {
return uv_poll_stop(poll_handle);
}
void Poller::onData(uv_poll_t* handle, int status, int events) {
Poller* obj = static_cast<Poller*>(handle->data);
Napi::Env env = obj->Env();
Napi::HandleScope scope(env);
// if Error
if (0 != status) {
// fprintf(stdout, "OnData Error status=%s events=%d\n", uv_strerror(status), events);
obj->_stop(); // doesn't matter if this errors
obj->callback.Call({Napi::Error::New(env, uv_strerror(status)).Value(), env.Undefined()});
} else {
// fprintf(stdout, "OnData status=%d events=%d subscribed=%d\n", status, events, obj->events);
// remove triggered events from the poll
int newEvents = obj->events & ~events;
obj->poll(env, newEvents);
obj->callback.Call({env.Null(), Napi::Number::New(env, events)});
}
}
Napi::Object Poller::Init(Napi::Env env, Napi::Object exports) {
Napi::Function func = DefineClass(env, "Poller", {
StaticMethod<&Poller::New>("New"),
InstanceMethod<&Poller::poll>("poll"),
InstanceMethod<&Poller::stop>("stop"),
InstanceMethod<&Poller::destroy>("destroy"),
});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
*constructor = Napi::Persistent(func);
exports.Set("Poller", func);
env.SetInstanceData<Napi::FunctionReference>(constructor);
return exports;
}
Napi::Value Poller::New(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "fd must be an int").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Value fd = info[0];
if (!info[1].IsFunction()) {
Napi::TypeError::New(env, "cb must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function callback = info[1].As<Napi::Function>();
Napi::FunctionReference* constructor = info.Env().GetInstanceData<Napi::FunctionReference>();
return constructor->New({fd, callback});
}
Napi::Value Poller::poll(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
Poller* obj = this;
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "events must be an int").ThrowAsJavaScriptException();
return env.Null();
}
int events = info[0].As<Napi::Number>().Int32Value();
obj->poll(env, events);
return env.Undefined();
}
Napi::Value Poller::stop(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
this->stop(env);
return env.Undefined();
}
Napi::Value Poller::destroy(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
Poller* obj = this;
// TODO Fix destruction Segfault
obj->Reset();
// delete obj;
return env.Undefined();
}
inline Napi::FunctionReference & Poller::constructor() {
static Napi::FunctionReference my_constructor;
// TODO Check if required
// my_constructor.SuppressDestruct();
return my_constructor;
}

35
node_modules/@serialport/bindings-cpp/src/poller.h generated vendored Normal file
View File

@@ -0,0 +1,35 @@
#ifndef PACKAGES_SERIALPORT_SRC_POLLER_H_
#define PACKAGES_SERIALPORT_SRC_POLLER_H_
#include <napi.h>
#include <uv.h>
class Poller : public Napi::ObjectWrap<Poller> {
public:
static Napi::Object Init(Napi::Env env, Napi::Object exports);
explicit Poller(const Napi::CallbackInfo &info);
static Napi::Value New(const Napi::CallbackInfo& info);
static void onData(uv_poll_t* handle, int status, int events);
static void onClose(uv_handle_t* poll_handle);
~Poller();
private:
int fd;
uv_poll_t* poll_handle = nullptr;
Napi::FunctionReference callback;
bool uv_poll_init_success = false;
// can this be read off of poll_handle?
int events = 0;
void poll(Napi::Env env, int events);
void stop(Napi::Env env);
int _stop();
Napi::Value poll(const Napi::CallbackInfo& info);
Napi::Value stop(const Napi::CallbackInfo& info);
Napi::Value destroy(const Napi::CallbackInfo& info);
static inline Napi::FunctionReference & constructor();
};
#endif // PACKAGES_SERIALPORT_SRC_POLLER_H_

View File

@@ -0,0 +1,342 @@
#include "./serialport.h"
#ifdef __APPLE__
#include "./darwin_list.h"
#endif
#ifdef WIN32
#define strncasecmp strnicmp
#include "./serialport_win.h"
#else
#include "./poller.h"
#endif
Napi::Value getValueFromObject(Napi::Object options, std::string key) {
Napi::String str = Napi::String::New(options.Env(), key);
return (options).Get(str);
}
int getIntFromObject(Napi::Object options, std::string key) {
return getValueFromObject(options, key).ToNumber().Int64Value();
}
bool getBoolFromObject(Napi::Object options, std::string key) {
return getValueFromObject(options, key).ToBoolean().Value();
}
Napi::String getStringFromObj(Napi::Object options, std::string key) {
return getValueFromObject(options, key).ToString();
}
double getDoubleFromObject(Napi::Object options, std::string key) {
return getValueFromObject(options, key).ToNumber().DoubleValue();
}
Napi::Value Open(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// path
if (!info[0].IsString()) {
Napi::TypeError::New(env, "First argument must be a string").ThrowAsJavaScriptException();
return env.Null();
}
std::string path = info[0].ToString().Utf8Value();
// options
if (!info[1].IsObject()) {
Napi::TypeError::New(env, "Second argument must be an object").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Object options = info[1].ToObject();
// callback
if (!info[2].IsFunction()) {
Napi::TypeError::New(env, "Third argument must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function callback = info[2].As<Napi::Function>();
OpenBaton* baton = new OpenBaton(callback);
snprintf(baton->path, sizeof(baton->path), "%s", path.c_str());
baton->baudRate = getIntFromObject(options, "baudRate");
baton->dataBits = getIntFromObject(options, "dataBits");
baton->parity = ToParityEnum(getStringFromObj(options, "parity"));
baton->stopBits = ToStopBitEnum(getDoubleFromObject(options, "stopBits"));
baton->rtscts = getBoolFromObject(options, "rtscts");
baton->rtsMode = ToRtsModeEnum(getStringFromObj(options, "rtsMode"));
baton->xon = getBoolFromObject(options, "xon");
baton->xoff = getBoolFromObject(options, "xoff");
baton->xany = getBoolFromObject(options, "xany");
baton->hupcl = getBoolFromObject(options, "hupcl");
baton->lock = getBoolFromObject(options, "lock");
#ifndef WIN32
baton->vmin = getIntFromObject(options, "vmin");
baton->vtime = getIntFromObject(options, "vtime");
#endif
baton->Queue();
return env.Undefined();
}
Napi::Value Update(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// file descriptor
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "First argument must be an int").ThrowAsJavaScriptException();
return env.Null();
}
int fd = info[0].As<Napi::Number>().Int32Value();
// options
if (!info[1].IsObject()) {
Napi::TypeError::New(env, "Second argument must be an object").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Object options = info[1].ToObject();
if (!(options).Has("baudRate")) {
Napi::TypeError::New(env, "\"baudRate\" must be set on options object").ThrowAsJavaScriptException();
return env.Null();
}
// callback
if (!info[2].IsFunction()) {
Napi::TypeError::New(env, "Third argument must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function callback = info[2].As<Napi::Function>();
ConnectionOptionsBaton* baton = new ConnectionOptionsBaton(callback);
baton->fd = fd;
baton->baudRate = getIntFromObject(options, "baudRate");
baton->Queue();
return env.Undefined();
}
Napi::Value Close(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// file descriptor
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "First argument must be an int").ThrowAsJavaScriptException();
return env.Null();
}
// callback
if (!info[1].IsFunction()) {
Napi::TypeError::New(env, "Second argument must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function callback = info[1].As<Napi::Function>();
CloseBaton* baton = new CloseBaton(callback);
baton->fd = info[0].ToNumber().Int64Value();;
baton->Queue();
return env.Undefined();
}
Napi::Value Flush(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// file descriptor
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "First argument must be an int").ThrowAsJavaScriptException();
return env.Null();
}
int fd = info[0].As<Napi::Number>().Int32Value();
// callback
if (!info[1].IsFunction()) {
Napi::TypeError::New(env, "Second argument must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function callback = info[1].As<Napi::Function>();
FlushBaton* baton = new FlushBaton(callback);
baton->fd = fd;
baton->Queue();
return env.Undefined();
}
Napi::Value Set(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// file descriptor
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "First argument must be an int").ThrowAsJavaScriptException();
return env.Null();
}
int fd = info[0].As<Napi::Number>().Int32Value();
// options
if (!info[1].IsObject()) {
Napi::TypeError::New(env, "Second argument must be an object").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Object options = info[1].ToObject();
// callback
if (!info[2].IsFunction()) {
Napi::TypeError::New(env, "Third argument must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function callback = info[2].As<Napi::Function>();
SetBaton* baton = new SetBaton(callback);
baton->fd = fd;
baton->brk = getBoolFromObject(options, "brk");
baton->rts = getBoolFromObject(options, "rts");
baton->cts = getBoolFromObject(options, "cts");
baton->dtr = getBoolFromObject(options, "dtr");
baton->dsr = getBoolFromObject(options, "dsr");
baton->lowLatency = getBoolFromObject(options, "lowLatency");
baton->Queue();
return env.Undefined();
}
Napi::Value Get(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// file descriptor
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "First argument must be an int").ThrowAsJavaScriptException();
return env.Null();
}
int fd = info[0].As<Napi::Number>().Int32Value();
// callback
if (!info[1].IsFunction()) {
Napi::TypeError::New(env, "Second argument must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function callback = info[1].As<Napi::Function>();
GetBaton* baton = new GetBaton(callback);
baton->fd = fd;
baton->cts = false;
baton->dsr = false;
baton->dcd = false;
baton->lowLatency = false;
baton->Queue();
return env.Undefined();
}
Napi::Value GetBaudRate(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// file descriptor
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "First argument must be an int").ThrowAsJavaScriptException();
return env.Null();
}
int fd = info[0].As<Napi::Number>().Int32Value();
// callback
if (!info[1].IsFunction()) {
Napi::TypeError::New(env, "Second argument must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function callback = info[1].As<Napi::Function>();
GetBaudRateBaton* baton = new GetBaudRateBaton(callback);
baton->fd = fd;
baton->baudRate = 0;
baton->Queue();
return env.Undefined();
}
Napi::Value Drain(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// file descriptor
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "First argument must be an int").ThrowAsJavaScriptException();
return env.Null();
}
int fd = info[0].As<Napi::Number>().Int32Value();
// callback
if (!info[1].IsFunction()) {
Napi::TypeError::New(env, "Second argument must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function callback = info[1].As<Napi::Function>();
DrainBaton* baton = new DrainBaton(callback);
baton->fd = fd;
baton->Queue();
return env.Undefined();
}
inline SerialPortParity ToParityEnum(const Napi::String& napistr) {
auto tmp = napistr.Utf8Value();
const char* str = tmp.c_str();
size_t count = strlen(str);
SerialPortParity parity = SERIALPORT_PARITY_NONE;
if (!strncasecmp(str, "none", count)) {
parity = SERIALPORT_PARITY_NONE;
} else if (!strncasecmp(str, "even", count)) {
parity = SERIALPORT_PARITY_EVEN;
} else if (!strncasecmp(str, "mark", count)) {
parity = SERIALPORT_PARITY_MARK;
} else if (!strncasecmp(str, "odd", count)) {
parity = SERIALPORT_PARITY_ODD;
} else if (!strncasecmp(str, "space", count)) {
parity = SERIALPORT_PARITY_SPACE;
}
return parity;
}
inline SerialPortStopBits ToStopBitEnum(double stopBits) {
if (stopBits > 1.4 && stopBits < 1.6) {
return SERIALPORT_STOPBITS_ONE_FIVE;
}
if (stopBits == 2) {
return SERIALPORT_STOPBITS_TWO;
}
return SERIALPORT_STOPBITS_ONE;
}
inline SerialPortRtsMode ToRtsModeEnum(const Napi::String& napistr) {
auto tmp = napistr.Utf8Value();
const char* str = tmp.c_str();
size_t count = strlen(str);
SerialPortRtsMode mode = SERIALPORT_RTSMODE_HANDSHAKE;
if (!strncasecmp(str, "enable", count)) {
mode = SERIALPORT_RTSMODE_ENABLE;
} else if (!strncasecmp(str, "handshake", count)) {
mode = SERIALPORT_RTSMODE_HANDSHAKE;
} else if (!strncasecmp(str, "toggle", count)) {
mode = SERIALPORT_RTSMODE_TOGGLE;
}
return mode;
}
Napi::Object init(Napi::Env env, Napi::Object exports) {
exports.Set("set", Napi::Function::New(env, Set));
exports.Set("get", Napi::Function::New(env, Get));
exports.Set("getBaudRate", Napi::Function::New(env, GetBaudRate));
exports.Set("open", Napi::Function::New(env, Open));
exports.Set("update", Napi::Function::New(env, Update));
exports.Set("close", Napi::Function::New(env, Close));
exports.Set("flush", Napi::Function::New(env, Flush));
exports.Set("drain", Napi::Function::New(env, Drain));
#ifdef __APPLE__
exports.Set("list", Napi::Function::New(env, List));
#endif
#ifdef WIN32
exports.Set("write", Napi::Function::New(env, Write));
exports.Set("read", Napi::Function::New(env, Read));
exports.Set("list", Napi::Function::New(env, List));
#else
Poller::Init(env, exports);
#endif
return exports;
}
NODE_API_MODULE(serialport, init);

202
node_modules/@serialport/bindings-cpp/src/serialport.h generated vendored Normal file
View File

@@ -0,0 +1,202 @@
#ifndef PACKAGES_SERIALPORT_SRC_SERIALPORT_H_
#define PACKAGES_SERIALPORT_SRC_SERIALPORT_H_
// Workaround for electron 11 abi issue https://github.com/serialport/node-serialport/issues/2191
// TODO Replace with ABI stable runtime check (per https://github.com/serialport/node-serialport/pull/2305#discussion_r697542996)
#include <node_version.h>
#if CHECK_NODE_API_MODULE_VERSION && NODE_API_MODULE_VERSION == 85
#define V8_REVERSE_JSARGS
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <napi.h>
#include <string>
#define ERROR_STRING_SIZE 1088
Napi::Value Open(const Napi::CallbackInfo& info);
Napi::Value Update(const Napi::CallbackInfo& info);
Napi::Value Close(const Napi::CallbackInfo& info);
Napi::Value Flush(const Napi::CallbackInfo& info);
Napi::Value Set(const Napi::CallbackInfo& info);
Napi::Value Get(const Napi::CallbackInfo& info);
Napi::Value GetBaudRate(const Napi::CallbackInfo& info);
Napi::Value Drain(const Napi::CallbackInfo& info);
enum SerialPortParity {
SERIALPORT_PARITY_NONE = 1,
SERIALPORT_PARITY_MARK = 2,
SERIALPORT_PARITY_EVEN = 3,
SERIALPORT_PARITY_ODD = 4,
SERIALPORT_PARITY_SPACE = 5
};
enum SerialPortStopBits {
SERIALPORT_STOPBITS_ONE = 1,
SERIALPORT_STOPBITS_ONE_FIVE = 2,
SERIALPORT_STOPBITS_TWO = 3
};
enum SerialPortRtsMode {
SERIALPORT_RTSMODE_ENABLE = 1,
SERIALPORT_RTSMODE_HANDSHAKE = 2,
SERIALPORT_RTSMODE_TOGGLE = 3
};
SerialPortParity ToParityEnum(const Napi::String& str);
SerialPortStopBits ToStopBitEnum(double stopBits);
SerialPortRtsMode ToRtsModeEnum(const Napi::String& str);
struct OpenBaton : public Napi::AsyncWorker {
OpenBaton(Napi::Function& callback) : Napi::AsyncWorker(callback, "node-serialport:OpenBaton"),
errorString(), path() {}
char errorString[ERROR_STRING_SIZE];
char path[1024];
int fd = 0;
int result = 0;
int baudRate = 0;
int dataBits = 0;
bool rtscts = false;
bool xon = false;
bool xoff = false;
bool xany = false;
bool hupcl = false;
bool lock = false;
SerialPortParity parity;
SerialPortStopBits stopBits;
SerialPortRtsMode rtsMode;
#ifndef WIN32
uint8_t vmin = 0;
uint8_t vtime = 0;
#endif
void Execute() override;
void OnOK() override {
Napi::Env env = Env();
Napi::HandleScope scope(env);
Callback().Call({env.Null(), Napi::Number::New(env, result)});
}
};
struct ConnectionOptions {
ConnectionOptions() : errorString() {}
char errorString[ERROR_STRING_SIZE];
int fd = 0;
int baudRate = 0;
};
struct ConnectionOptionsBaton : ConnectionOptions , Napi::AsyncWorker {
ConnectionOptionsBaton(Napi::Function& callback) : ConnectionOptions() , Napi::AsyncWorker(callback, "node-serialport:ConnectionOptionsBaton") {}
void Execute() override;
void OnOK() override {
Napi::Env env = Env();
Napi::HandleScope scope(env);
Callback().Call({env.Null()});
}
};
struct SetBaton : public Napi::AsyncWorker {
SetBaton(Napi::Function& callback) : Napi::AsyncWorker(callback, "node-serialport:SetBaton"),
errorString() {}
int fd = 0;
int result = 0;
char errorString[ERROR_STRING_SIZE];
bool rts = false;
bool cts = false;
bool dtr = false;
bool dsr = false;
bool brk = false;
bool lowLatency = false;
void Execute() override;
void OnOK() override {
Napi::Env env = Env();
Napi::HandleScope scope(env);
Callback().Call({env.Null()});
}
};
struct GetBaton : public Napi::AsyncWorker {
GetBaton(Napi::Function& callback) : Napi::AsyncWorker(callback, "node-serialport:GetBaton"),
errorString() {}
int fd = 0;
char errorString[ERROR_STRING_SIZE];
bool cts = false;
bool dsr = false;
bool dcd = false;
bool lowLatency = false;
void Execute() override;
void OnOK() override {
Napi::Env env = Env();
Napi::HandleScope scope(env);
Napi::Object results = Napi::Object::New(env);
results.Set("cts", cts);
results.Set("dsr", dsr);
results.Set("dcd", dcd);
results.Set("lowLatency", lowLatency);
Callback().Call({env.Null(), results});
}
};
struct GetBaudRateBaton : public Napi::AsyncWorker {
GetBaudRateBaton(Napi::Function& callback) : Napi::AsyncWorker(callback, "node-serialport:GetBaudRateBaton"),
errorString() {}
int fd = 0;
char errorString[ERROR_STRING_SIZE];
int baudRate = 0;
void Execute() override;
void OnOK() override {
Napi::Env env = Env();
Napi::HandleScope scope(env);
Napi::Object results = Napi::Object::New(env);
(results).Set(Napi::String::New(env, "baudRate"), Napi::Number::New(env, baudRate));
Callback().Call({env.Null(),results});
}
};
struct VoidBaton : public Napi::AsyncWorker {
VoidBaton(Napi::Function& callback, const char *resource_name) : Napi::AsyncWorker(callback, resource_name),
errorString() {}
int fd = 0;
char errorString[ERROR_STRING_SIZE];
void OnOK() override {
Napi::Env env = Env();
Napi::HandleScope scope(env);
Callback().Call({env.Null()});
}
};
struct CloseBaton : VoidBaton {
CloseBaton(Napi::Function& callback) : VoidBaton(callback, "node-serialport:CloseBaton") {}
void Execute() override;
};
struct DrainBaton : VoidBaton {
DrainBaton(Napi::Function& callback) : VoidBaton(callback, "node-serialport:DrainBaton") {}
void Execute() override;
};
struct FlushBaton : VoidBaton {
FlushBaton(Napi::Function& callback) : VoidBaton(callback, "node-serialport:FlushBaton") {}
void Execute() override;
};
int setup(int fd, OpenBaton *data);
int setBaudRate(ConnectionOptions *data);
#endif // PACKAGES_SERIALPORT_SRC_SERIALPORT_H_

View File

@@ -0,0 +1,76 @@
#if defined(__linux__)
#include <sys/ioctl.h>
#include <asm/ioctls.h>
#include <asm/termbits.h>
#include <linux/serial.h>
// Uses the termios2 interface to set nonstandard baud rates
int linuxSetCustomBaudRate(const int fd, const unsigned int baudrate) {
struct termios2 t;
if (ioctl(fd, TCGETS2, &t) == -1) {
return -1;
}
t.c_cflag &= ~CBAUD;
t.c_cflag |= BOTHER;
t.c_ospeed = t.c_ispeed = baudrate;
if (ioctl(fd, TCSETS2, &t) == -1) {
return -2;
}
return 0;
}
// Uses termios2 interface to retrieve system reported baud rate
int linuxGetSystemBaudRate(const int fd, int* const outbaud) {
struct termios2 t;
if (ioctl(fd, TCGETS2, &t) == -1) {
return -1;
}
*outbaud = static_cast<int>(t.c_ospeed);
return 0;
}
int linuxSetLowLatencyMode(const int fd, const bool enable) {
struct serial_struct ss;
if (ioctl(fd, TIOCGSERIAL, &ss) == -1) {
return -1;
}
if ((ss.flags & ASYNC_LOW_LATENCY) == enable) {
return 0;
}
if (enable) {
ss.flags |= ASYNC_LOW_LATENCY;
} else {
ss.flags &= ~ASYNC_LOW_LATENCY;
}
if (ioctl(fd, TIOCSSERIAL, &ss) == -1) {
return -2;
}
return 0;
}
int linuxGetLowLatencyMode(const int fd, bool* const enabled) {
struct serial_struct ss;
if (ioctl(fd, TIOCGSERIAL, &ss) == -1) {
return -1;
}
*enabled = ss.flags & ASYNC_LOW_LATENCY;
return 0;
}
#endif

10
node_modules/@serialport/bindings-cpp/src/serialport_linux.h generated vendored Executable file
View File

@@ -0,0 +1,10 @@
#ifndef PACKAGES_SERIALPORT_SRC_SERIALPORT_LINUX_H_
#define PACKAGES_SERIALPORT_SRC_SERIALPORT_LINUX_H_
int linuxSetCustomBaudRate(const int fd, const unsigned int baudrate);
int linuxGetSystemBaudRate(const int fd, int* const outbaud);
int linuxSetLowLatencyMode(const int fd, const bool enable);
int linuxGetLowLatencyMode(const int fd, bool* const enabled);
#endif // PACKAGES_SERIALPORT_SRC_SERIALPORT_LINUX_H_

View File

@@ -0,0 +1,482 @@
#include "serialport_unix.h"
#include "serialport.h"
#include <sys/file.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#ifdef __APPLE__
#include <AvailabilityMacros.h>
#include <sys/param.h>
#endif
#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
#include <sys/ioctl.h>
#include <IOKit/serial/ioss.h>
#elif defined(__NetBSD__)
#include <sys/ioctl.h>
#elif defined(__OpenBSD__)
#include <sys/ioctl.h>
#elif defined(__linux__)
#include <sys/ioctl.h>
#include <linux/serial.h>
#include "serialport_linux.h"
#endif
int ToStopBitsConstant(SerialPortStopBits stopBits);
int ToBaudConstant(int baudRate) {
switch (baudRate) {
case 0: return B0;
case 50: return B50;
case 75: return B75;
case 110: return B110;
case 134: return B134;
case 150: return B150;
case 200: return B200;
case 300: return B300;
case 600: return B600;
case 1200: return B1200;
case 1800: return B1800;
case 2400: return B2400;
case 4800: return B4800;
case 9600: return B9600;
case 19200: return B19200;
case 38400: return B38400;
case 57600: return B57600;
case 115200: return B115200;
case 230400: return B230400;
#if defined(__linux__)
case 460800: return B460800;
case 500000: return B500000;
case 576000: return B576000;
case 921600: return B921600;
case 1000000: return B1000000;
case 1152000: return B1152000;
case 1500000: return B1500000;
case 2000000: return B2000000;
case 2500000: return B2500000;
case 3000000: return B3000000;
case 3500000: return B3500000;
case 4000000: return B4000000;
#endif
}
return -1;
}
int ToDataBitsConstant(int dataBits) {
switch (dataBits) {
case 8: default: return CS8;
case 7: return CS7;
case 6: return CS6;
case 5: return CS5;
}
return -1;
}
void OpenBaton::Execute() {
int flags = (O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC | O_SYNC);
int fd = open(path, flags);
if (-1 == fd) {
snprintf(errorString, sizeof(errorString), "Error: %s, cannot open %s", strerror(errno), path);
this->SetError(errorString);
return;
}
if (-1 == setup(fd, this)) {
this->SetError(errorString);
close(fd);
return;
}
result = fd;
}
void ConnectionOptionsBaton::Execute() {
// lookup the standard baudrates from the table
int baudRate = ToBaudConstant(this->baudRate);
// get port options
struct termios options;
if (-1 == tcgetattr(fd, &options)) {
snprintf(errorString, sizeof(errorString), "Error: %s setting custom baud rate of %d", strerror(errno), baudRate);
this->SetError(errorString);
return;
}
// If there is a custom baud rate on linux you can do the following trick with B38400
#if defined(__linux__) && defined(ASYNC_SPD_CUST)
if (baudRate == -1) {
int err = linuxSetCustomBaudRate(fd, this->baudRate);
if (err == -1) {
snprintf(errorString, sizeof(errorString), "Error: %s || while retrieving termios2 info", strerror(errno));
this->SetError(errorString);
return;
} else if (err == -2) {
snprintf(errorString, sizeof(errorString), "Error: %s || while setting custom baud rate of %d", strerror(errno), this->baudRate);
this->SetError(errorString);
return;
}
return;
}
#endif
// On OS X, starting with Tiger, we can set a custom baud rate with ioctl
#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
if (-1 == baudRate) {
speed_t speed = this->baudRate;
if (-1 == ioctl(fd, IOSSIOSPEED, &speed)) {
snprintf(errorString, sizeof(errorString), "Error: %s calling ioctl(.., IOSSIOSPEED, %ld )", strerror(errno), speed);
this->SetError(errorString);
return;
} else {
tcflush(fd, TCIOFLUSH);
return;
}
}
#endif
if (-1 == baudRate) {
snprintf(errorString, sizeof(errorString), "Error baud rate of %d is not supported on your platform", baudRate);
this->SetError(errorString);
return;
}
// If we have a good baud rate set it and lets go
cfsetospeed(&options, baudRate);
cfsetispeed(&options, baudRate);
// throw away all the buffered data
tcflush(fd, TCIOFLUSH);
// make the changes now
tcsetattr(fd, TCSANOW, &options);
return;
}
int setup(int fd, OpenBaton *data) {
int dataBits = ToDataBitsConstant(data->dataBits);
if (-1 == dataBits) {
snprintf(data->errorString, sizeof(data->errorString),"Invalid data bits setting %d", data->dataBits);
return -1;
}
// Snow Leopard doesn't have O_CLOEXEC
if (-1 == fcntl(fd, F_SETFD, FD_CLOEXEC)) {
snprintf(data->errorString, sizeof(data->errorString), "Error %s Cannot open %s", strerror(errno), data->path);
return -1;
}
// Get port configuration for modification
struct termios options;
tcgetattr(fd, &options);
// IGNPAR: ignore bytes with parity errors
options.c_iflag = IGNPAR;
// ICRNL: map CR to NL (otherwise a CR input on the other computer will not terminate input)
// Future potential option
// options.c_iflag = ICRNL;
// otherwise make device raw (no other input processing)
// Specify data bits
options.c_cflag &= ~CSIZE;
options.c_cflag |= dataBits;
options.c_cflag &= ~(CRTSCTS);
if (data->rtscts) {
options.c_cflag |= CRTSCTS;
// evaluate specific flow control options
}
options.c_iflag &= ~(IXON | IXOFF | IXANY);
if (data->xon) {
options.c_iflag |= IXON;
}
if (data->xoff) {
options.c_iflag |= IXOFF;
}
if (data->xany) {
options.c_iflag |= IXANY;
}
switch (data->parity) {
case SERIALPORT_PARITY_NONE:
options.c_cflag &= ~PARENB;
// options.c_cflag &= ~CSTOPB;
// options.c_cflag &= ~CSIZE;
// options.c_cflag |= CS8;
break;
case SERIALPORT_PARITY_ODD:
options.c_cflag |= PARENB;
options.c_cflag |= PARODD;
// options.c_cflag &= ~CSTOPB;
// options.c_cflag &= ~CSIZE;
// options.c_cflag |= CS7;
break;
case SERIALPORT_PARITY_EVEN:
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
// options.c_cflag &= ~CSTOPB;
// options.c_cflag &= ~CSIZE;
// options.c_cflag |= CS7;
break;
default:
snprintf(data->errorString, sizeof(data->errorString), "Invalid parity setting %d", data->parity);
return -1;
}
switch (data->stopBits) {
case SERIALPORT_STOPBITS_ONE:
options.c_cflag &= ~CSTOPB;
break;
case SERIALPORT_STOPBITS_TWO:
options.c_cflag |= CSTOPB;
break;
default:
snprintf(data->errorString, sizeof(data->errorString), "Invalid stop bits setting %d", data->stopBits);
return -1;
}
options.c_cflag |= CLOCAL; // ignore status lines
options.c_cflag |= CREAD; // enable receiver
if (data->hupcl) {
options.c_cflag |= HUPCL; // drop DTR (i.e. hangup) on close
}
// Raw output
options.c_oflag = 0;
// ICANON makes partial lines not readable. It should be optional.
// It works with ICRNL.
options.c_lflag = 0; // ICANON;
options.c_cc[VMIN]= data->vmin;
options.c_cc[VTIME]= data->vtime;
// Note that tcsetattr() returns success if any of the requested changes could be successfully carried out.
// Therefore, when making multiple changes it may be necessary to follow this call with a further call to
// tcgetattr() to check that all changes have been performed successfully.
// This also fails on OSX
tcsetattr(fd, TCSANOW, &options);
if (data->lock) {
if (-1 == flock(fd, LOCK_EX | LOCK_NB)) {
snprintf(data->errorString, sizeof(data->errorString), "Error %s Cannot lock port", strerror(errno));
return -1;
}
}
// Copy the connection options into the ConnectionOptionsBaton to set the baud rate
ConnectionOptions* connectionOptions = new ConnectionOptions();
connectionOptions->fd = fd;
connectionOptions->baudRate = data->baudRate;
if (-1 == setBaudRate(connectionOptions)) {
strncpy(data->errorString, connectionOptions->errorString, sizeof(data->errorString));
delete(connectionOptions);
return -1;
}
delete(connectionOptions);
// flush all unread and wrote data up to this point because it could have been received or sent with bad settings
// Not needed since setBaudRate does this for us
// tcflush(fd, TCIOFLUSH);
return 1;
}
int setBaudRate(ConnectionOptions *data) {
// lookup the standard baudrates from the table
int baudRate = ToBaudConstant(data->baudRate);
int fd = data->fd;
// get port options
struct termios options;
if (-1 == tcgetattr(fd, &options)) {
snprintf(data->errorString, sizeof(data->errorString),
"Error: %s setting custom baud rate of %d", strerror(errno), data->baudRate);
return -1;
}
// If there is a custom baud rate on linux you can do the following trick with B38400
#if defined(__linux__) && defined(ASYNC_SPD_CUST)
if (baudRate == -1) {
int err = linuxSetCustomBaudRate(fd, data->baudRate);
if (err == -1) {
snprintf(data->errorString, sizeof(data->errorString),
"Error: %s || while retrieving termios2 info", strerror(errno));
return -1;
} else if (err == -2) {
snprintf(data->errorString, sizeof(data->errorString),
"Error: %s || while setting custom baud rate of %d", strerror(errno), data->baudRate);
return -1;
}
return 1;
}
#endif
// On OS X, starting with Tiger, we can set a custom baud rate with ioctl
#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
if (-1 == baudRate) {
speed_t speed = data->baudRate;
if (-1 == ioctl(fd, IOSSIOSPEED, &speed)) {
snprintf(data->errorString, sizeof(data->errorString),
"Error: %s calling ioctl(.., IOSSIOSPEED, %ld )", strerror(errno), speed);
return -1;
} else {
tcflush(fd, TCIOFLUSH);
return 1;
}
}
#endif
if (-1 == baudRate) {
snprintf(data->errorString, sizeof(data->errorString), "Error baud rate of %d is not supported on your platform", data->baudRate);
return -1;
}
// If we have a good baud rate set it and lets go
cfsetospeed(&options, baudRate);
cfsetispeed(&options, baudRate);
// throw away all the buffered data
tcflush(fd, TCIOFLUSH);
// make the changes now
tcsetattr(fd, TCSANOW, &options);
return 1;
}
void CloseBaton::Execute() {
if (-1 == close(fd)) {
snprintf(errorString, sizeof(errorString), "Error: %s, unable to close fd %d", strerror(errno), fd);
this->SetError(errorString);
}
}
void SetBaton::Execute() {
int bits;
ioctl(fd, TIOCMGET, &bits);
bits &= ~(TIOCM_RTS | TIOCM_CTS | TIOCM_DTR | TIOCM_DSR);
if (rts) {
bits |= TIOCM_RTS;
}
if (cts) {
bits |= TIOCM_CTS;
}
if (dtr) {
bits |= TIOCM_DTR;
}
if (dsr) {
bits |= TIOCM_DSR;
}
int result = 0;
if (brk) {
result = ioctl(fd, TIOCSBRK, NULL);
} else {
result = ioctl(fd, TIOCCBRK, NULL);
}
if (-1 == result) {
snprintf(errorString, sizeof(errorString), "Error: %s, cannot set", strerror(errno));
this->SetError(errorString);
return;
}
if (-1 == ioctl(fd, TIOCMSET, &bits)) {
snprintf(errorString, sizeof(errorString), "Error: %s, cannot set", strerror(errno));
this->SetError(errorString);
return;
}
#if defined(__linux__)
int err = linuxSetLowLatencyMode(fd, lowLatency);
// Only report errors when the lowLatency is being set to true. Attempting to set as false can error, since the default is false
if (lowLatency) {
if (err == -1) {
snprintf(errorString, sizeof(errorString), "Error: %s, cannot get low latency", strerror(errno));
return;
} else if(err == -2) {
snprintf(errorString, sizeof(errorString), "Error: %s, cannot set low latency", strerror(errno));
return;
}
}
#endif
}
void GetBaton::Execute() {
int bits;
if (-1 == ioctl(fd, TIOCMGET, &bits)) {
snprintf(errorString, sizeof(errorString), "Error: %s, cannot get", strerror(errno));
this->SetError(errorString);
return;
}
cts = bits & TIOCM_CTS;
dsr = bits & TIOCM_DSR;
dcd = bits & TIOCM_CD;
#if defined(__linux__) && defined(ASYNC_LOW_LATENCY)
bool lowlatency = false;
// Try to get low latency info, but we don't care if fails (a failure state will still return lowlatency = false)
linuxGetLowLatencyMode(fd, &lowlatency);
lowLatency = lowlatency;
#else
lowLatency = false;
#endif
}
void GetBaudRateBaton::Execute() {
int outbaud = -1;
#if defined(__linux__) && defined(ASYNC_SPD_CUST)
if (-1 == linuxGetSystemBaudRate(fd, &outbaud)) {
snprintf(errorString, sizeof(errorString), "Error: %s, cannot get baud rate", strerror(errno));
this->SetError(errorString);
return;
}
#else
snprintf(errorString, sizeof(errorString), "Error: System baud rate check not implemented on this platform");
this->SetError(errorString);
return;
#endif
baudRate = outbaud;
}
void FlushBaton::Execute() {
if (-1 == tcflush(fd, TCIOFLUSH)) {
snprintf(errorString, sizeof(errorString), "Error: %s, cannot flush", strerror(errno));
this->SetError(errorString);
return;
}
}
void DrainBaton::Execute() {
if (-1 == tcdrain(fd)) {
snprintf(errorString, sizeof(errorString), "Error: %s, cannot drain", strerror(errno));
this->SetError(errorString);
return;
}
}

View File

@@ -0,0 +1,7 @@
#ifndef PACKAGES_SERIALPORT_SRC_SERIALPORT_UNIX_H_
#define PACKAGES_SERIALPORT_SRC_SERIALPORT_UNIX_H_
int ToBaudConstant(int baudRate);
int ToDataBitsConstant(int dataBits);
#endif // PACKAGES_SERIALPORT_SRC_SERIALPORT_UNIX_H_

View File

@@ -0,0 +1,964 @@
#include "./serialport.h"
#include "./serialport_win.h"
#include <napi.h>
#include <uv.h>
#include <list>
#include <vector>
#include <string.h>
#include <windows.h>
#include <Setupapi.h>
#include <initguid.h>
#include <devpkey.h>
#include <devguid.h>
#include <wchar.h>
#pragma comment(lib, "setupapi.lib")
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
#define MAX_BUFFER_SIZE 1000
// As per https://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
#define MAX_REGISTRY_KEY_SIZE 255
// Declare type of pointer to CancelIoEx function
typedef BOOL (WINAPI *CancelIoExType)(HANDLE hFile, LPOVERLAPPED lpOverlapped);
std::list<int> g_closingHandles;
void ErrorCodeToString(const wchar_t* prefix, int errorCode, wchar_t *errorStr) {
switch (errorCode) {
case ERROR_FILE_NOT_FOUND:
_snwprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, L"%ls: File not found", prefix);
break;
case ERROR_INVALID_HANDLE:
_snwprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, L"%ls: Invalid handle", prefix);
break;
case ERROR_ACCESS_DENIED:
_snwprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, L"%ls: Access denied", prefix);
break;
case ERROR_OPERATION_ABORTED:
_snwprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, L"%ls: Operation aborted", prefix);
break;
case ERROR_INVALID_PARAMETER:
_snwprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, L"%ls: The parameter is incorrect %d", prefix, errorCode);
break;
default:
_snwprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, L"%ls: Unknown error code %d", prefix, errorCode);
break;
}
}
void ErrorCodeToString(const char* prefix, int errorCode, char *errorStr) {
switch (errorCode) {
case ERROR_FILE_NOT_FOUND:
_snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: File not found", prefix);
break;
case ERROR_INVALID_HANDLE:
_snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Invalid handle", prefix);
break;
case ERROR_ACCESS_DENIED:
_snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Access denied", prefix);
break;
case ERROR_OPERATION_ABORTED:
_snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Operation aborted", prefix);
break;
case ERROR_INVALID_PARAMETER:
_snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: The parameter is incorrect", prefix);
break;
default:
_snprintf_s(errorStr, ERROR_STRING_SIZE, _TRUNCATE, "%s: Unknown error code %d", prefix, errorCode);
break;
}
}
void AsyncCloseCallback(uv_handle_t* handle) {
uv_async_t* async = reinterpret_cast<uv_async_t*>(handle);
delete async;
}
void OpenBaton::Execute() {
char originalPath[1024];
strncpy_s(originalPath, sizeof(originalPath), path, _TRUNCATE);
// path is char[1024] but on Windows it has the form "COMx\0" or "COMxx\0"
// We want to prepend "\\\\.\\" to it before we call CreateFile
strncpy(path + 20, path, 10);
strncpy(path, "\\\\.\\", 4);
strncpy(path + 4, path + 20, 10);
int shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
if (lock) {
shareMode = 0;
}
HANDLE file = CreateFile(
path,
GENERIC_READ | GENERIC_WRITE,
shareMode, // dwShareMode 0 Prevents other processes from opening if they request delete, read, or write access
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, // allows for reading and writing at the same time and sets the handle for asynchronous I/O
NULL);
if (file == INVALID_HANDLE_VALUE) {
DWORD errorCode = GetLastError();
char temp[100];
_snprintf_s(temp, sizeof(temp), _TRUNCATE, "Opening %s", originalPath);
ErrorCodeToString(temp, errorCode, errorString);
this->SetError(errorString);
return;
}
DCB dcb = { 0 };
SecureZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
if (!GetCommState(file, &dcb)) {
ErrorCodeToString("Open (GetCommState)", GetLastError(), errorString);
this->SetError(errorString);
CloseHandle(file);
return;
}
if (hupcl) {
dcb.fDtrControl = DTR_CONTROL_ENABLE;
} else {
dcb.fDtrControl = DTR_CONTROL_DISABLE; // disable DTR to avoid reset
}
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fOutxDsrFlow = FALSE;
dcb.fOutxCtsFlow = FALSE;
if (xon) {
dcb.fOutX = TRUE;
} else {
dcb.fOutX = FALSE;
}
if (xoff) {
dcb.fInX = TRUE;
} else {
dcb.fInX = FALSE;
}
if (rtscts) {
switch (rtsMode) {
case SERIALPORT_RTSMODE_ENABLE:
dcb.fRtsControl = RTS_CONTROL_ENABLE;
break;
case SERIALPORT_RTSMODE_HANDSHAKE:
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
break;
case SERIALPORT_RTSMODE_TOGGLE:
dcb.fRtsControl = RTS_CONTROL_TOGGLE;
break;
}
dcb.fOutxCtsFlow = TRUE;
} else {
dcb.fRtsControl = RTS_CONTROL_DISABLE;
}
dcb.fBinary = true;
dcb.BaudRate = baudRate;
dcb.ByteSize = dataBits;
switch (parity) {
case SERIALPORT_PARITY_NONE:
dcb.Parity = NOPARITY;
break;
case SERIALPORT_PARITY_MARK:
dcb.Parity = MARKPARITY;
break;
case SERIALPORT_PARITY_EVEN:
dcb.Parity = EVENPARITY;
break;
case SERIALPORT_PARITY_ODD:
dcb.Parity = ODDPARITY;
break;
case SERIALPORT_PARITY_SPACE:
dcb.Parity = SPACEPARITY;
break;
}
switch (stopBits) {
case SERIALPORT_STOPBITS_ONE:
dcb.StopBits = ONESTOPBIT;
break;
case SERIALPORT_STOPBITS_ONE_FIVE:
dcb.StopBits = ONE5STOPBITS;
break;
case SERIALPORT_STOPBITS_TWO:
dcb.StopBits = TWOSTOPBITS;
break;
}
if (!SetCommState(file, &dcb)) {
ErrorCodeToString("Open (SetCommState)", GetLastError(), errorString);
this->SetError(errorString);
CloseHandle(file);
return;
}
// Set the timeouts for read and write operations.
// Read operation will wait for at least 1 byte to be received.
COMMTIMEOUTS commTimeouts = {};
commTimeouts.ReadIntervalTimeout = 0; // Never timeout, always wait for data.
commTimeouts.ReadTotalTimeoutMultiplier = 0; // Do not allow big read timeout when big read buffer used
commTimeouts.ReadTotalTimeoutConstant = 0; // Total read timeout (period of read loop)
commTimeouts.WriteTotalTimeoutConstant = 0; // Const part of write timeout
commTimeouts.WriteTotalTimeoutMultiplier = 0; // Variable part of write timeout (per byte)
if (!SetCommTimeouts(file, &commTimeouts)) {
ErrorCodeToString("Open (SetCommTimeouts)", GetLastError(), errorString);
this->SetError(errorString);
CloseHandle(file);
return;
}
// Remove garbage data in RX/TX queues
PurgeComm(file, PURGE_RXCLEAR);
PurgeComm(file, PURGE_TXCLEAR);
result = static_cast<int>(reinterpret_cast<uintptr_t>(file));
}
void ConnectionOptionsBaton::Execute() {
DCB dcb = { 0 };
SecureZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
if (!GetCommState(int2handle(fd), &dcb)) {
ErrorCodeToString("Update (GetCommState)", GetLastError(), errorString);
this->SetError(errorString);
return;
}
dcb.BaudRate = baudRate;
if (!SetCommState(int2handle(fd), &dcb)) {
ErrorCodeToString("Update (SetCommState)", GetLastError(), errorString);
this->SetError(errorString);
return;
}
}
void SetBaton::Execute() {
if (rts) {
EscapeCommFunction(int2handle(fd), SETRTS);
} else {
EscapeCommFunction(int2handle(fd), CLRRTS);
}
if (dtr) {
EscapeCommFunction(int2handle(fd), SETDTR);
} else {
EscapeCommFunction(int2handle(fd), CLRDTR);
}
if (brk) {
EscapeCommFunction(int2handle(fd), SETBREAK);
} else {
EscapeCommFunction(int2handle(fd), CLRBREAK);
}
DWORD bits = 0;
GetCommMask(int2handle(fd), &bits);
bits &= ~(EV_CTS | EV_DSR);
if (cts) {
bits |= EV_CTS;
}
if (dsr) {
bits |= EV_DSR;
}
if (!SetCommMask(int2handle(fd), bits)) {
ErrorCodeToString("Setting options on COM port (SetCommMask)", GetLastError(), errorString);
this->SetError(errorString);
return;
}
}
void GetBaton::Execute() {
DWORD bits = 0;
if (!GetCommModemStatus(int2handle(fd), &bits)) {
ErrorCodeToString("Getting control settings on COM port (GetCommModemStatus)", GetLastError(), errorString);
this->SetError(errorString);
return;
}
cts = bits & MS_CTS_ON;
dsr = bits & MS_DSR_ON;
dcd = bits & MS_RLSD_ON;
}
void GetBaudRateBaton::Execute() {
DCB dcb = { 0 };
SecureZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
if (!GetCommState(int2handle(fd), &dcb)) {
ErrorCodeToString("Getting baud rate (GetCommState)", GetLastError(), errorString);
this->SetError(errorString);
return;
}
baudRate = static_cast<int>(dcb.BaudRate);
}
bool IsClosingHandle(int fd) {
for (std::list<int>::iterator it = g_closingHandles.begin(); it != g_closingHandles.end(); ++it) {
if (fd == *it) {
g_closingHandles.remove(fd);
return true;
}
}
return false;
}
void __stdcall WriteIOCompletion(DWORD errorCode, DWORD bytesTransferred, OVERLAPPED* ov) {
WriteBaton* baton = static_cast<WriteBaton*>(ov->hEvent);
DWORD bytesWritten;
if (!GetOverlappedResult(int2handle(baton->fd), ov, &bytesWritten, TRUE)) {
errorCode = GetLastError();
ErrorCodeToString("Writing to COM port (GetOverlappedResult)", errorCode, baton->errorString);
baton->complete = true;
return;
}
if (bytesWritten) {
baton->offset += bytesWritten;
if (baton->offset >= baton->bufferLength) {
baton->complete = true;
}
}
}
DWORD __stdcall WriteThread(LPVOID param) {
uv_async_t* async = static_cast<uv_async_t*>(param);
WriteBaton* baton = static_cast<WriteBaton*>(async->data);
OVERLAPPED* ov = new OVERLAPPED;
memset(ov, 0, sizeof(OVERLAPPED));
ov->hEvent = static_cast<void*>(baton);
while (!baton->complete) {
char* offsetPtr = baton->bufferData + baton->offset;
// WriteFileEx requires calling GetLastError even upon success. Clear the error beforehand.
SetLastError(0);
WriteFileEx(int2handle(baton->fd), offsetPtr,
static_cast<DWORD>(baton->bufferLength - baton->offset), ov, WriteIOCompletion);
// Error codes when call is successful, such as ERROR_MORE_DATA.
DWORD lastError = GetLastError();
if (lastError != ERROR_SUCCESS) {
ErrorCodeToString("Writing to COM port (WriteFileEx)", lastError, baton->errorString);
break;
}
// IOCompletion routine is only called once this thread is in an alertable wait state.
SleepEx(INFINITE, TRUE);
}
delete ov;
// Signal the main thread to run the callback.
uv_async_send(async);
ExitThread(0);
}
void EIO_AfterWrite(uv_async_t* req) {
WriteBaton* baton = static_cast<WriteBaton*>(req->data);
Napi::Env env = baton->callback.Env();
Napi::HandleScope scope(env);
WaitForSingleObject(baton->hThread, INFINITE);
CloseHandle(baton->hThread);
uv_close(reinterpret_cast<uv_handle_t*>(req), AsyncCloseCallback);
v8::Local<v8::Value> argv[1];
if (baton->errorString[0]) {
baton->callback.Call({Napi::Error::New(env, baton->errorString).Value()});
} else {
baton->callback.Call({env.Null()});
}
baton->buffer.Reset();
delete baton;
}
Napi::Value Write(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// file descriptor
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "First argument must be an int").ThrowAsJavaScriptException();
return env.Null();
}
int fd = info[0].As<Napi::Number>().Int32Value();
// buffer
if (!info[1].IsObject() || !info[1].IsBuffer()) {
Napi::TypeError::New(env, "Second argument must be a buffer").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Buffer<char> buffer = info[1].As<Napi::Buffer<char>>();
//getBufferFromObject(info[1].ToObject().ti);
char* bufferData = buffer.Data(); //.As<Napi::Buffer<char>>().Data();
size_t bufferLength = buffer.Length();//.As<Napi::Buffer<char>>().Length();
// callback
if (!info[2].IsFunction()) {
Napi::TypeError::New(env, "Third argument must be a function").ThrowAsJavaScriptException();
return env.Null();
}
WriteBaton* baton = new WriteBaton();
baton->callback = Napi::Persistent(info[2].As<Napi::Function>());
baton->fd = fd;
baton->buffer.Reset(buffer);
baton->bufferData = bufferData;
baton->bufferLength = bufferLength;
baton->offset = 0;
baton->complete = false;
uv_async_t* async = new uv_async_t;
uv_async_init(uv_default_loop(), async, EIO_AfterWrite);
async->data = baton;
// WriteFileEx requires a thread that can block. Create a new thread to
// run the write operation, saving the handle so it can be deallocated later.
baton->hThread = CreateThread(NULL, 0, WriteThread, async, 0, NULL);
return env.Null();
}
void __stdcall ReadIOCompletion(DWORD errorCode, DWORD bytesTransferred, OVERLAPPED* ov) {
ReadBaton* baton = static_cast<ReadBaton*>(ov->hEvent);
if (errorCode) {
ErrorCodeToString("Reading from COM port (ReadIOCompletion)", errorCode, baton->errorString);
baton->complete = true;
return;
}
DWORD lastError;
if (!GetOverlappedResult(int2handle(baton->fd), ov, &bytesTransferred, TRUE)) {
lastError = GetLastError();
ErrorCodeToString("Reading from COM port (GetOverlappedResult)", lastError, baton->errorString);
baton->complete = true;
return;
}
if (bytesTransferred) {
baton->bytesToRead -= bytesTransferred;
baton->bytesRead += bytesTransferred;
baton->offset += bytesTransferred;
}
if (!baton->bytesToRead) {
baton->complete = true;
CloseHandle(ov->hEvent);
return;
}
// ReadFileEx and GetOverlappedResult retrieved only 1 byte. Read any additional data in the input
// buffer. Set the timeout to MAXDWORD in order to disable timeouts, so the read operation will
// return immediately no matter how much data is available.
COMMTIMEOUTS commTimeouts = {};
commTimeouts.ReadIntervalTimeout = MAXDWORD;
if (!SetCommTimeouts(int2handle(baton->fd), &commTimeouts)) {
lastError = GetLastError();
ErrorCodeToString("Setting COM timeout (SetCommTimeouts)", lastError, baton->errorString);
baton->complete = true;
// CloseHandle(ov->hEvent); // wondering if we need to close the handle here
return;
}
// Store additional data after whatever data has already been read.
char* offsetPtr = baton->bufferData + baton->offset;
// ReadFile, unlike ReadFileEx, needs an event in the overlapped structure.
memset(ov, 0, sizeof(OVERLAPPED));
ov->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!ReadFile(int2handle(baton->fd), offsetPtr, baton->bytesToRead, &bytesTransferred, ov)) {
errorCode = GetLastError();
if (errorCode != ERROR_IO_PENDING) {
ErrorCodeToString("Reading from COM port (ReadFile)", errorCode, baton->errorString);
baton->complete = true;
CloseHandle(ov->hEvent);
return;
}
if (!GetOverlappedResult(int2handle(baton->fd), ov, &bytesTransferred, TRUE)) {
lastError = GetLastError();
ErrorCodeToString("Reading from COM port (GetOverlappedResult)", lastError, baton->errorString);
baton->complete = true;
CloseHandle(ov->hEvent);
return;
}
}
baton->bytesToRead -= bytesTransferred;
baton->bytesRead += bytesTransferred;
baton->complete = true;
CloseHandle(ov->hEvent);
}
DWORD __stdcall ReadThread(LPVOID param) {
uv_async_t* async = static_cast<uv_async_t*>(param);
ReadBaton* baton = static_cast<ReadBaton*>(async->data);
DWORD lastError;
OVERLAPPED* ov = new OVERLAPPED;
memset(ov, 0, sizeof(OVERLAPPED));
ov->hEvent = static_cast<void*>(baton);
while (!baton->complete) {
// Reset the read timeout to 0, so that it will block until more data arrives.
COMMTIMEOUTS commTimeouts = {};
commTimeouts.ReadIntervalTimeout = 0;
if (!SetCommTimeouts(int2handle(baton->fd), &commTimeouts)) {
lastError = GetLastError();
ErrorCodeToString("Setting COM timeout (SetCommTimeouts)", lastError, baton->errorString);
break;
}
// ReadFileEx doesn't use overlapped's hEvent, so it is reserved for user data.
ov->hEvent = static_cast<HANDLE>(baton);
char* offsetPtr = baton->bufferData + baton->offset;
// ReadFileEx requires calling GetLastError even upon success. Clear the error beforehand.
SetLastError(0);
// Only read 1 byte, so that the callback will be triggered once any data arrives.
ReadFileEx(int2handle(baton->fd), offsetPtr, 1, ov, ReadIOCompletion);
// Error codes when call is successful, such as ERROR_MORE_DATA.
lastError = GetLastError();
if (lastError != ERROR_SUCCESS) {
ErrorCodeToString("Reading from COM port (ReadFileEx)", lastError, baton->errorString);
break;
}
// IOCompletion routine is only called once this thread is in an alertable wait state.
SleepEx(INFINITE, TRUE);
}
delete ov;
// Signal the main thread to run the callback.
uv_async_send(async);
ExitThread(0);
}
void EIO_AfterRead(uv_async_t* req) {
ReadBaton* baton = static_cast<ReadBaton*>(req->data);
Napi::Env env = baton->callback.Env();
Napi::HandleScope scope(env);
WaitForSingleObject(baton->hThread, INFINITE);
CloseHandle(baton->hThread);
uv_close(reinterpret_cast<uv_handle_t*>(req), AsyncCloseCallback);
if (baton->errorString[0]) {
baton->callback.Call({Napi::Error::New(env, baton->errorString).Value(), env.Undefined()});
} else {
baton->callback.Call({env.Null(), Napi::Number::New(env, static_cast<int>(baton->bytesRead))});
}
delete baton;
}
Napi::Value Read(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// file descriptor
if (!info[0].IsNumber()) {
Napi::TypeError::New(env, "First argument must be a fd").ThrowAsJavaScriptException();
return env.Null();
}
int fd = info[0].As<Napi::Number>().Int32Value();
// buffer
if (!info[1].IsObject() || !info[1].IsBuffer()) {
Napi::TypeError::New(env, "Second argument must be a buffer").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Object buffer = info[1].ToObject();
size_t bufferLength = buffer.As<Napi::Buffer<char>>().Length();
// offset
if (!info[2].IsNumber()) {
Napi::TypeError::New(env, "Third argument must be an int").ThrowAsJavaScriptException();
return env.Null();
}
int offset = info[2].ToNumber().Int64Value();
// bytes to read
if (!info[3].IsNumber()) {
Napi::TypeError::New(env, "Fourth argument must be an int").ThrowAsJavaScriptException();
return env.Null();
}
size_t bytesToRead = info[3].ToNumber().Int64Value();
if ((bytesToRead + offset) > bufferLength) {
Napi::TypeError::New(env, "'bytesToRead' + 'offset' cannot be larger than the buffer's length").ThrowAsJavaScriptException();
return env.Null();
}
// callback
if (!info[4].IsFunction()) {
Napi::TypeError::New(env, "Fifth argument must be a function").ThrowAsJavaScriptException();
return env.Null();
}
ReadBaton* baton = new ReadBaton();
baton->callback = Napi::Persistent(info[4].As<Napi::Function>());
baton->fd = fd;
baton->offset = offset;
baton->bytesToRead = bytesToRead;
baton->bufferLength = bufferLength;
baton->bufferData = buffer.As<Napi::Buffer<char>>().Data();
baton->complete = false;
uv_async_t* async = new uv_async_t;
uv_async_init(uv_default_loop(), async, EIO_AfterRead);
async->data = baton;
baton->hThread = CreateThread(NULL, 0, ReadThread, async, 0, NULL);
// ReadFileEx requires a thread that can block. Create a new thread to
// run the read operation, saving the handle so it can be deallocated later.
return env.Null();
}
void CloseBaton::Execute() {
g_closingHandles.push_back(fd);
HMODULE hKernel32 = LoadLibrary("kernel32.dll");
// Look up function address
CancelIoExType pCancelIoEx = (CancelIoExType)GetProcAddress(hKernel32, "CancelIoEx");
// Do something with it
if (pCancelIoEx) {
// Function exists so call it
// Cancel all pending IO Requests for the current device
pCancelIoEx(int2handle(fd), NULL);
}
if (!CloseHandle(int2handle(fd))) {
ErrorCodeToString("Closing connection (CloseHandle)", GetLastError(), errorString);
this->SetError(errorString);
return;
}
}
wchar_t *copySubstring(wchar_t *someString, int n) {
wchar_t *new_ = reinterpret_cast<wchar_t*>(malloc(sizeof(wchar_t)*n + 1));
wcsncpy_s(new_, n + 1, someString, n);
new_[n] = '\0';
return new_;
}
Napi::Value List(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// callback
if (!info[0].IsFunction()) {
Napi::TypeError::New(env, "First argument must be a function").ThrowAsJavaScriptException();
return env.Null();
}
Napi::Function callback = info[0].As<Napi::Function>();
ListBaton* baton = new ListBaton(callback);
_snwprintf(baton->errorString, sizeof(baton->errorString), L"");
baton->Queue();
return env.Undefined();
}
// It's possible that the s/n is a construct and not the s/n of the parent USB
// composite device. This performs some convoluted registry lookups to fetch the USB s/n.
void getSerialNumber(const wchar_t *vid,
const wchar_t *pid,
const HDEVINFO hDevInfo,
SP_DEVINFO_DATA deviceInfoData,
const unsigned int maxSerialNumberLength,
wchar_t* serialNumber) {
_snwprintf_s(serialNumber, maxSerialNumberLength, _TRUNCATE, L"");
if (vid == NULL || pid == NULL) {
return;
}
DWORD dwSize;
WCHAR szWUuidBuffer[MAX_BUFFER_SIZE];
WCHAR wantedUuid[MAX_BUFFER_SIZE];
// Fetch the "Container ID" for this device node. In USB context, this "Container
// ID" refers to the composite USB device, i.e. the USB device as a whole, not
// just one of its interfaces with a serial port driver attached.
// From https://stackoverflow.com/questions/3438366/setupdigetdeviceproperty-usage-example:
// Because this is not compiled with UNICODE defined, the call to SetupDiGetDevicePropertyW
// has to be setup manually.
DEVPROPTYPE ulPropertyType;
typedef BOOL (WINAPI *FN_SetupDiGetDevicePropertyW)(
__in HDEVINFO DeviceInfoSet,
__in PSP_DEVINFO_DATA DeviceInfoData,
__in const DEVPROPKEY *PropertyKey,
__out DEVPROPTYPE *PropertyType,
__out_opt PBYTE PropertyBuffer,
__in DWORD PropertyBufferSize,
__out_opt PDWORD RequiredSize,
__in DWORD Flags);
FN_SetupDiGetDevicePropertyW fn_SetupDiGetDevicePropertyW = (FN_SetupDiGetDevicePropertyW)
GetProcAddress(GetModuleHandle(TEXT("Setupapi.dll")), "SetupDiGetDevicePropertyW");
if (fn_SetupDiGetDevicePropertyW (
hDevInfo,
&deviceInfoData,
&DEVPKEY_Device_ContainerId,
&ulPropertyType,
reinterpret_cast<BYTE*>(szWUuidBuffer),
sizeof(szWUuidBuffer),
&dwSize,
0)) {
szWUuidBuffer[dwSize] = '\0';
// Given the UUID bytes, build up a (widechar) string from it. There's some mangling
// going on.
StringFromGUID2((REFGUID)szWUuidBuffer, wantedUuid, ARRAY_SIZE(wantedUuid));
} else {
// Container UUID could not be fetched, return empty serial number.
return;
}
// NOTE: Devices might have a containerUuid like {00000000-0000-0000-FFFF-FFFFFFFFFFFF}
// This means they're non-removable, and are not handled (yet).
// Maybe they should inherit the s/n from somewhere else.
// Iterate through all the USB devices with the given VendorID/ProductID
HKEY vendorProductHKey;
DWORD retCode;
wchar_t hkeyPath[MAX_BUFFER_SIZE];
_snwprintf_s(hkeyPath, MAX_BUFFER_SIZE, _TRUNCATE, L"SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_%s&PID_%s", vid, pid);
retCode = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
hkeyPath,
0,
KEY_READ,
&vendorProductHKey);
if (retCode == ERROR_SUCCESS) {
DWORD serialNumbersCount = 0; // number of subkeys
// Fetch how many subkeys there are for this VendorID/ProductID pair.
// That's the number of devices for this VendorID/ProductID known to this machine.
retCode = RegQueryInfoKey(
vendorProductHKey, // hkey handle
NULL, // buffer for class name
NULL, // size of class string
NULL, // reserved
&serialNumbersCount, // number of subkeys
NULL, // longest subkey size
NULL, // longest class string
NULL, // number of values for this key
NULL, // longest value name
NULL, // longest value data
NULL, // security descriptor
NULL); // last write time
if (retCode == ERROR_SUCCESS && serialNumbersCount > 0) {
for (unsigned int i=0; i < serialNumbersCount; i++) {
// Each of the subkeys here is the serial number of a USB device with the
// given VendorId/ProductId. Now fetch the string for the S/N.
DWORD serialNumberLength = maxSerialNumberLength;
retCode = RegEnumKeyExW(vendorProductHKey,
i,
reinterpret_cast<LPWSTR>(serialNumber),
&serialNumberLength,
NULL,
NULL,
NULL,
NULL);
if (retCode == ERROR_SUCCESS) {
// Lookup info for VID_(vendorId)&PID_(productId)\(serialnumber)
_snwprintf_s(hkeyPath, MAX_BUFFER_SIZE, _TRUNCATE,
L"SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_%ls&PID_%ls\\%ls",
vid, pid, serialNumber);
HKEY deviceHKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, hkeyPath, 0, KEY_READ, &deviceHKey) == ERROR_SUCCESS) {
wchar_t readUuid[MAX_BUFFER_SIZE];
DWORD readSize = sizeof(readUuid);
// Query VID_(vendorId)&PID_(productId)\(serialnumber)\ContainerID
retCode = RegQueryValueExW(deviceHKey, L"ContainerID", NULL, NULL, (LPBYTE)&readUuid, &readSize);
if (retCode == ERROR_SUCCESS) {
readUuid[readSize] = '\0';
if (wcscmp(wantedUuid, readUuid) == 0) {
// The ContainerID UUIDs match, return now that serialNumber has
// the right value.
RegCloseKey(deviceHKey);
RegCloseKey(vendorProductHKey);
return;
}
}
}
RegCloseKey(deviceHKey);
}
}
}
/* In case we did not obtain the path, for whatever reason, we close the key and return an empty string. */
RegCloseKey(vendorProductHKey);
}
_snwprintf_s(serialNumber, maxSerialNumberLength, _TRUNCATE, L"");
return;
}
void ListBaton::Execute() {
GUID *guidDev = (GUID*)& GUID_DEVCLASS_PORTS; // NOLINT
HDEVINFO hDevInfo = SetupDiGetClassDevs(guidDev, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE);
SP_DEVINFO_DATA deviceInfoData;
int memberIndex = 0;
DWORD dwSize, dwPropertyRegDataType;
wchar_t szBuffer[MAX_BUFFER_SIZE];
wchar_t *pnpId;
wchar_t *vendorId;
wchar_t *productId;
wchar_t *name;
wchar_t *manufacturer;
wchar_t *locationId;
wchar_t *friendlyName;
wchar_t serialNumber[MAX_REGISTRY_KEY_SIZE];
bool isCom;
while (true) {
isCom = false;
pnpId = NULL;
vendorId = NULL;
productId = NULL;
name = NULL;
manufacturer = NULL;
locationId = NULL;
friendlyName = NULL;
ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA));
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiEnumDeviceInfo(hDevInfo, memberIndex, &deviceInfoData) == FALSE) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) {
break;
}
}
dwSize = sizeof(szBuffer);
SetupDiGetDeviceInstanceIdW(hDevInfo, &deviceInfoData, reinterpret_cast<PWSTR>(szBuffer), dwSize, &dwSize);
szBuffer[dwSize] = '\0';
pnpId = wcsdup(szBuffer);
vendorId = wcsstr(szBuffer, L"VID_");
if (vendorId) {
vendorId += 4;
vendorId = copySubstring(vendorId, 4);
}
productId = wcsstr(szBuffer, L"PID_");
if (productId) {
productId += 4;
productId = copySubstring(productId, 4);
}
getSerialNumber(vendorId, productId, hDevInfo, deviceInfoData, MAX_REGISTRY_KEY_SIZE, serialNumber);
if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &deviceInfoData,
SPDRP_LOCATION_INFORMATION, &dwPropertyRegDataType,
reinterpret_cast<PBYTE>(szBuffer), sizeof(szBuffer), &dwSize)) {
locationId = wcsdup(szBuffer);
}
if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &deviceInfoData,
SPDRP_FRIENDLYNAME, &dwPropertyRegDataType,
reinterpret_cast<PBYTE>(szBuffer), sizeof(szBuffer), &dwSize)) {
friendlyName = wcsdup(szBuffer);
}
if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &deviceInfoData,
SPDRP_MFG, &dwPropertyRegDataType,
reinterpret_cast<PBYTE>(szBuffer), sizeof(szBuffer), &dwSize)) {
manufacturer = wcsdup(szBuffer);
}
HKEY hkey = SetupDiOpenDevRegKey(hDevInfo, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
if (hkey != INVALID_HANDLE_VALUE) {
dwSize = sizeof(szBuffer);
if (RegQueryValueExW(hkey, L"PortName", NULL, NULL, (LPBYTE)&szBuffer, &dwSize) == ERROR_SUCCESS) {
name = wcsdup(szBuffer);
szBuffer[dwSize] = '\0';
isCom = wcsstr(szBuffer, L"COM") != NULL;
}
}
if (isCom) {
ListResultItem* resultItem = new ListResultItem();
resultItem->path = name;
resultItem->manufacturer = manufacturer;
resultItem->pnpId = pnpId;
if (vendorId) {
resultItem->vendorId = vendorId;
}
if (productId) {
resultItem->productId = productId;
}
resultItem->serialNumber = serialNumber;
if (locationId) {
resultItem->locationId = locationId;
}
if (friendlyName) {
resultItem->friendlyName = friendlyName;
}
results.push_back(resultItem);
}
free(pnpId);
free(vendorId);
free(productId);
free(locationId);
free(manufacturer);
free(name);
RegCloseKey(hkey);
memberIndex++;
}
if (hDevInfo) {
SetupDiDestroyDeviceInfoList(hDevInfo);
}
}
void setIfNotEmpty(Napi::Object item, std::string key, const char *value) {
Napi::Env env = item.Env();
Napi::String v8key = Napi::String::New(env, key);
if (strlen(value) > 0) {
(item).Set(v8key, Napi::String::New(env, value));
} else {
(item).Set(v8key, env.Undefined());
}
}
void setIfNotEmpty(Napi::Object item, std::string key, const wchar_t *value) {
Napi::Env env = item.Env();
Napi::String v8key = Napi::String::New(env, key);
if (wcslen(value) > 0) {
(item).Set(v8key, Napi::String::New(env, (const char16_t*) value));
} else {
(item).Set(v8key, env.Undefined());
}
}
void FlushBaton::Execute() {
DWORD purge_all = PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR;
if (!PurgeComm(int2handle(fd), purge_all)) {
ErrorCodeToString("Flushing connection (PurgeComm)", GetLastError(), errorString);
this->SetError(errorString);
return;
}
}
void DrainBaton::Execute() {
if (!FlushFileBuffers(int2handle(fd))) {
ErrorCodeToString("Draining connection (FlushFileBuffers)", GetLastError(), errorString);
this->SetError(errorString);
return;
}
}

View File

@@ -0,0 +1,93 @@
#ifndef PACKAGES_SERIALPORT_SRC_SERIALPORT_WIN_H_
#define PACKAGES_SERIALPORT_SRC_SERIALPORT_WIN_H_
#include <napi.h>
#include <uv.h>
#include <node_buffer.h>
#include <list>
#include <string>
#define ERROR_STRING_SIZE 1088
static inline HANDLE int2handle(int ptr) {
return reinterpret_cast<HANDLE>(static_cast<uintptr_t>(ptr));
}
struct WriteBaton {
WriteBaton() : bufferData(), errorString() {}
int fd = 0;
char* bufferData = nullptr;
size_t bufferLength = 0;
size_t offset = 0;
size_t bytesWritten = 0;
void* hThread = nullptr;
bool complete = false;
Napi::ObjectReference buffer;
Napi::FunctionReference callback;
int result = 0;
char errorString[ERROR_STRING_SIZE];
};
Napi::Value Write(const Napi::CallbackInfo& info);
struct ReadBaton {
ReadBaton() : errorString() {}
int fd = 0;
char* bufferData = nullptr;
size_t bufferLength = 0;
size_t bytesRead = 0;
size_t bytesToRead = 0;
size_t offset = 0;
void* hThread = nullptr;
Napi::FunctionReference callback;
bool complete = false;
char errorString[ERROR_STRING_SIZE];
};
Napi::Value Read(const Napi::CallbackInfo& info);
Napi::Value List(const Napi::CallbackInfo& info);
void setIfNotEmpty(Napi::Object item, std::string key, const char *value);
void setIfNotEmpty(Napi::Object item, std::string key, const wchar_t *value);
struct ListResultItem {
std::wstring path;
std::wstring manufacturer;
std::wstring serialNumber;
std::wstring pnpId;
std::wstring locationId;
std::wstring friendlyName;
std::wstring vendorId;
std::wstring productId;
};
struct ListBaton : public Napi::AsyncWorker {
ListBaton(Napi::Function& callback) : Napi::AsyncWorker(callback, "node-serialport:ListBaton"),
errorString() {}
std::list<ListResultItem*> results;
wchar_t errorString[ERROR_STRING_SIZE];
void Execute() override;
void OnOK() override {
Napi::Env env = Env();
Napi::HandleScope scope(env);
Napi::Array result = Napi::Array::New(env);
int i = 0;
for (std::list<ListResultItem*>::iterator it = results.begin(); it != results.end(); ++it, i++) {
Napi::Object item = Napi::Object::New(env);
setIfNotEmpty(item, "path", (*it)->path.c_str());
setIfNotEmpty(item, "manufacturer", (*it)->manufacturer.c_str());
setIfNotEmpty(item, "serialNumber", (*it)->serialNumber.c_str());
setIfNotEmpty(item, "pnpId", (*it)->pnpId.c_str());
setIfNotEmpty(item, "locationId", (*it)->locationId.c_str());
setIfNotEmpty(item, "friendlyName", (*it)->friendlyName.c_str());
setIfNotEmpty(item, "vendorId", (*it)->vendorId.c_str());
setIfNotEmpty(item, "productId", (*it)->productId.c_str());
(result).Set(i, item);
}
Callback().Call({env.Null(), result});
}
};
#endif // PACKAGES_SERIALPORT_SRC_SERIALPORT_WIN_H_