1
0
mirror of https://github.com/wjwwood/serial.git synced 2026-01-22 11:44:53 +08:00

Compare commits

...

85 Commits
1.2.0 ... main

Author SHA1 Message Date
Eric Fontaine
69e0372cf0
Move License text to separate LICENSE file (#261) 2022-03-08 16:16:57 -08:00
Maicol Castro
33e5a31ab7
Fix broken links (#244) 2021-06-10 15:15:44 -07:00
Robin Krens
ed9f89ca31
Add support for serial bluetooth ports on Linux (#237)
Added search blob /dev/rfcomm*. rfcomm* is a commonly used naming
convention for bluetooth ports on linux
2021-06-10 15:14:48 -07:00
Jacob Perron
9fc9e81fc1
Remove Boost dependency (#235)
It wasn't being used so there's no need to depend on it.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2021-06-10 15:14:20 -07:00
Matthias Behr
57f72772a9
Add EINTR handling to SerialImpl::write (#233)
EINTR can still happen on write. Don't throw the exception in that
case but retry.
In case of other errors add more details to the SerialException.
2021-06-10 15:13:58 -07:00
Atomie CHEN
a93fc844d9
Solve issue Custom Baudrate OSX #139 of original repo; inspired by PySerial source code and #57 of github.com/npat-efault/picocom, we need to set custom baudrate after calling tcsetattr; tested on macOS Mojave 10.14.4 (#218) 2021-06-10 14:57:40 -07:00
Hannes Kamecke
7439db1228
Fix windows com port prefix (#179)
The check in `_prefix_port_if_needed` does not work, as it's currently comparing the whole input string to the prefix. As a consequence, port strings will be prefixed, even if they're already prefixed. This commit changes the call to `wstring::compare` to use an overload that compares a substring of the input string only.
2021-06-10 14:57:28 -07:00
Chenchen
9e331e7977
fix invalid memory access when eol size >1 (#220)
Co-authored-by: chenguojun <chenguojun@yogorobot.com>
2021-06-10 14:49:29 -07:00
Sean Yen
cbcca7c837 Install serial library to a portable location. (#216) 2020-01-06 11:15:17 -08:00
bsbaliga
683e12d2f6 Fix memory leak when exception is thrown by impl classes in (#198)
Serial::read() vector and string variants.
2019-03-25 15:25:33 -07:00
William Woodall
fba8d81b5d
whitespace 2018-11-12 12:03:16 -06:00
William Woodall
2ef29d7b10
whitespace 2018-11-12 12:01:58 -06:00
William Woodall
5a354eaab7
reduce the number of jobs on travis (#172)
* reduce the number of jobs on travis

* update usage of pip due to changes in Homebrew

* update pip and ensure the right one is being used with an alias

* force reinstall pip to get `pip` on PATH

* use python2 explicitly to run catkin_make

* force use of python2 executable by catkin packages

* python!

* simpler

* how to which

* Update .travis.yml

* make tests and run_tests

* test results

* disable timer tests on macOS
2018-02-05 19:44:04 -08:00
Mike Purvis
bdba3a80ad Fix CMake warning for rt and pthread. (#165) 2018-01-18 17:25:29 -08:00
William Woodall
17e3223e68
remove references to no longer available uninstall command (#171) 2018-01-13 13:37:26 -08:00
William Woodall
764fab8b5e sublime project file updates 2018-01-13 13:19:48 -08:00
Ben Moyer
235a5f716d print GetLastError() result instead of errno (#154) 2018-01-13 12:16:50 -08:00
Ben Moyer
534141aa8f implement flushInput and flushOutput for windows (#153) 2018-01-13 12:15:36 -08:00
José Manuel Díez
ce085ce88c Problem: hardware flow control uses RTS_CONTROL_TOGGLE (#132)
RTS_CONTROL_HANDSHAKE raises RTS when there is space in the input
buffer; RTS_CONTROL_TOGGLE only raises RTS when bytes are available for
transmission.

Also replace numeric constants with symbolic constants.
2018-01-13 12:10:11 -08:00
Mike Purvis
d3713af096 Support 500kbps serial ports. (#167) 2018-01-09 07:22:43 -08:00
rhd
827c4a784d Fix issue with write() and a timeout of 0. (#137)
* Fix issue with write() and a timeout of 0.

* fix up style
2017-01-20 17:34:49 -08:00
Stephane Poirier
771e62c220 Update documentation (#140)
* Fix typo and missing dependency in README

* [docs] Update docs: fix deprecation warnings + add missing deps to README
2017-01-20 15:29:03 -08:00
aleksey-sergey
02dfff7883 fixing unix timeouts handling ("timer_tests.short_interval" failure) (#147) 2016-11-28 17:38:53 -08:00
aleksey-sergey
4d69fb2e41 fix timeouts handling on Unix systems (#142)
fixed "singed long" overflow that took place on attempt
to use ~3000ms or bigger timeouts on Unix systems
2016-11-28 14:06:00 -08:00
dontsovcmc
c16faab6ea resource leak if exception in SerialImpl constructor (#146) 2016-11-21 14:48:07 -08:00
Christopher Baker
d76b7d6b7f Const corrections. (#141) 2016-10-17 13:54:11 +09:00
William Woodall
2d416f1560 Merge pull request #118 from Rimco/patch-1
Updated serial.cc for FreeBSD 9 compatibility.
2015-12-02 09:06:25 -08:00
Rimco
22dce33fa4 Updated serial.cc for FreeBSD 9 compatibility. 2015-11-26 22:15:48 +01:00
William Woodall
e12d81eadf Merge pull request #116 from pao/patch-1
Use CLOCK_MONOTONIC (Linux)/SYSTEM_CLOCK (OS X) to time select()
2015-11-10 15:35:05 -08:00
Patrick O'Leary
c5b4bbd181 on OS X, use SYSTEM_CLOCK, not CALENDAR_CLOCK
Analogously to using `CLOCK_MONOTONIC` on Linux to time events in favor of `CLOCK_REALTIME`, `SYSTEM_CLOCK` should be used in favor of `CALENDAR_CLOCK` on OS X.

Ref: http://stackoverflow.com/questions/11680461/monotonic-clock-on-osx
2015-11-10 17:28:45 -06:00
Patrick O'Leary
98f1c31e81 on Linux, use CLOCK_MONOTONIC for clock_gettime()
On Linux systems which are being driven by an external time source (NTP or PTP), it is possible that time appears to slew in reverse under `CLOCK_REALTIME`. Since the timer function is used to time durations of events (calls to `select()`), it is better to use `CLOCK_MONOTONIC`, which isn't subject to slewing.
2015-11-10 09:40:30 -06:00
William Woodall
ef7f77d411 Merge pull request #113 from vladimirgamalian/patch-1
Comment unreferenced formal parameters
2015-09-27 14:14:03 -07:00
Vladimir Gamalian
402657574c Comment unreferenced formal parameter
Fix warning from static analysis tools.
2015-09-27 19:41:56 +07:00
William Woodall
a81087ec85 Merge pull request #112 from linquize/vs2015
Support VS2015
2015-09-23 14:35:04 -07:00
Linquize
9b80fc3fbf Can use the toolsets from Visual Studio 2010, 2012, 2013, 2015 2015-09-22 21:45:43 +08:00
William Woodall
c57285f30a Merge pull request #106 from ramirahikkala/master
AdditionalIncludeDirectories must be relative for project not solution
2015-08-14 10:11:13 -07:00
Rami
cd5053cb32 AdditionalIncludeDirectories must be relative for project not solution
Fixes #105

Signed-off-by: Rami <rami.rahikkala@jotautomation.com>
2015-08-14 08:37:27 +03:00
William Woodall
6144d579af Merge pull request #103 from drummist180/master
Fix include directory paths in Visual Studio projects.
2015-07-21 16:02:36 -07:00
Brandon Morton
1580f10d39 Fix include directory paths in Visual Studio projects.
Remove previously ignored *.user file.
2015-07-16 19:17:52 -07:00
William Woodall
99e57e633c Merge pull request #98 from wjwwood/fix_issue_97
fix warning on Windows
2015-04-27 15:20:05 -07:00
William Woodall
b8320d31a7 fix warning on Windows 2015-04-27 14:44:16 -07:00
William Woodall
10ac4e1c25 1.2.1 2015-04-21 21:50:41 -07:00
William Woodall
03ca3be6a8 Merge pull request #96 from wjwwood/issue_84
fix handling of COM ports over 10 on Windows, fixes #84
2015-04-21 21:38:04 -07:00
William Woodall
52197afbc8 [doc] fixup/clarify some throws documentation 2015-04-21 21:15:51 -07:00
William Woodall
e438077cba [style] whitespace and configs 2015-04-21 21:15:51 -07:00
William Woodall
985c3a5172 fix handling of COM ports over 10 on Windows, fixes #84 2015-04-21 20:43:54 -07:00
William Woodall
1a70b09bb1 Merge pull request #95 from wjwwood/issue_90_refresh
Release io_iterator_t object when finished with it in list_ports_osx.cc.
2015-04-21 20:42:02 -07:00
William Woodall
33bbde42c8 fix typo 2015-04-21 20:07:55 -07:00
William Woodall
3a9e6be834 [style] whitespace 2015-04-21 19:01:59 -07:00
Konstantina Kastanara
42aa78ae98 Release io_iterator_t object when finished with it in list_ports_osx.cc. 2015-04-21 18:59:58 -07:00
William Woodall
d7084ce775 Merge pull request #93 from legath/master
fix for clang build on macosx
2015-04-06 12:04:08 -07:00
Alexander Bulychev
e26a977173 fix for clang build on macosx 2015-04-06 16:53:33 +03:00
William Woodall
5b13be4d7c Merge pull request #92 from DarkDemiurg/master
Fix for mingw32
2015-03-24 16:56:05 -07:00
DarkDemiurg
29cb551c41 Fix for mingw32 2015-03-24 23:19:15 +03:00
William Woodall
e70643380d Merge pull request #91 from wjwwood/fix_osx
travis: fixup os x dep install
2015-03-09 13:04:19 -07:00
William Woodall
32792b3ee1 travis: fixup os x dep install 2015-03-09 11:48:31 -07:00
William Woodall
2473a8770f Merge pull request #86 from avian2/add-57600-baud
Add 576000 baud support for Unix
2015-01-12 10:34:06 -08:00
Tomaz Solc
dda5b6308e Add 576000 baud support for Unix 2015-01-06 15:15:31 +01:00
William Woodall
17da2dea31 Add CI status to README.md 2014-12-29 12:40:54 -08:00
William Woodall
c3d55880c8 Merge pull request #85 from wjwwood/travis_osx2
trying different travis osx settings
2014-12-29 12:37:37 -08:00
William Woodall
bd0980b69a trying different travis osx settings 2014-12-29 11:48:58 -08:00
William Woodall
31fa9c9e34 Merge pull request #83 from wjwwood/travis_osx
trying out osx support in travis
2014-12-29 11:22:22 -08:00
William Woodall
a622105543 trying out osx support in travis 2014-12-29 11:19:57 -08:00
William Woodall
8036553a1e improve error message when mark or space parity are not supported 2014-12-09 13:50:24 -08:00
David Hodo
6f464948f0 Make MARK/SPACE partiy support optional 2014-12-09 14:50:37 -06:00
William Woodall
6e47bdd0ae Merge pull request #81 from achronop/master
Add MARK/SPACE parity bit option
2014-12-07 15:20:49 -08:00
achronop
b376f85fb0 Add MARK/SPACE parity bit option 2014-12-07 21:33:53 +02:00
William Woodall
c19a5a3cc9 Merge pull request #75 from Konstantinacc/master
CloseHanle fd_ if SetCommState fails in function Serial::SerialImpl::reconfigurePort ().
2014-08-19 10:16:54 -07:00
Konstantina Kastanara
7bce3e0fdc CloseHanle fd_ if SetCommState fails in function Serial::SerialImpl::reconfigurePort (). 2014-08-19 18:24:48 +03:00
William Woodall
7de61c1603 Merge pull request #72 from dawid-aurobit/mxe-cross
support for mxe (http://mxe.cc)
2014-08-16 20:26:21 -07:00
Dawid Piotrowski
49b6762927 support for mxe 2014-08-16 22:08:56 +02:00
William Woodall
8fe085c45f Merge pull request #69 from linquize/vs
Many Visual Studio fixes
2014-07-27 14:38:49 -07:00
Linquize
b55e9f797f Can use the toolsets from Visual Studio 2010, 2012, 2013
The default is v100 (VS2010)
2014-07-26 22:00:10 +08:00
Linquize
54d7a9474a Fix warning in Win64 2014-07-26 21:59:53 +08:00
William Woodall
88ee4b3e3b Merge pull request #70 from bakercp/bugfix-availability-macros
Add include for OSX version checking macros.
2014-07-21 13:04:49 -07:00
Christopher Baker
3f0d49a602 Make sure AvailabilityMacros.h is included for build systems that do not include it by default.
- Required for macros such as MAC_OS_X_VERSION_10_3, MAC_OS_X_VERSION_MIN_REQUIRED, etc.
2014-07-21 12:29:38 -05:00
Linquize
124e601d2f Add VS related ignore files to .gitignore 2014-07-19 20:49:45 +08:00
Linquize
60bb787f93 Add x64 Platform to VS project 2014-07-19 20:49:08 +08:00
Linquize
d107487228 Add <SubSystem> tags to VS projects, specifically, test_serial is a console application 2014-07-19 20:48:23 +08:00
Linquize
e315dc5a48 Make Release|Win32 configuration compile 2014-07-19 20:13:56 +08:00
William Woodall
17aac9b77d Merge pull request #68 from bakercp/mingw_vs_text
Fixes to allow cross correct encoding on both codeblocks / mingw and VS
2014-07-15 13:35:28 -07:00
Christopher Baker
24564c59d3 Remove confusing comment. 2014-07-13 09:17:27 -05:00
William Woodall
1697fe2c56 Merge pull request #67 from bakercp/no_cpp11_codeblocks_win
Revert c++11 feature for better backward compatibility.
2014-07-12 14:16:31 -07:00
Christopher Baker
d9847ff87b Fixes to allow cross correct encoding on both codeblocsk / mingw and visual studio. 2014-07-11 09:28:55 -05:00
Christopher Baker
e16f43b1e4 Revert c++11 feature for better backward compatibility. 2014-07-10 23:57:19 -05:00
24 changed files with 2126 additions and 1083 deletions

7
.gitignore vendored
View File

@ -25,3 +25,10 @@ msg_gen
srv_gen srv_gen
doc/html doc/html
*sublime-workspace *sublime-workspace
*.user
*.suo
*.sdf
*.opensdf
ipch
Debug
Release

View File

@ -1,12 +1,10 @@
os:
- linux
- osx
language: cpp language: cpp
compiler:
- gcc
- clang
install: install:
- sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu precise main" > /etc/apt/sources.list.d/ros-latest.list' - make install_deps
- wget http://packages.ros.org/ros.key -O - | sudo apt-key add - - source setup.bash
- sudo apt-get update
- sudo apt-get install ros-groovy-catkin libboost-dev
- source /opt/ros/groovy/setup.bash
script: script:
- make && make test - mkdir build && cd build && cmake .. -DPYTHON_EXECUTABLE=$(which python2) && make && make tests && make run_tests
- catkin_test_results .

View File

@ -2,6 +2,22 @@
Changelog for package serial Changelog for package serial
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1.2.1 (2015-04-21)
------------------
* Removed the use of a C++11 feature for compatibility with older browsers.
* Fixed an issue with cross compiling with mingw on Windows.
* Restructured Visual Studio project layout.
* Added include of ``#include <AvailabilityMacros.h>`` on OS X (listing of ports).
* Fixed MXE for the listing of ports on Windows.
* Now closes file device if ``reconfigureDevice`` fails (Windows).
* Added the MARK/SPACE parity bit option, also made it optional.
Adding the enumeration values for MARK and SPACE was the only code change to an API header.
It should not affect ABI or API.
* Added support for 576000 baud on Linux.
* Now releases iterator properly in listing of ports code for OS X.
* Fixed the ability to open COM ports over COM10 on Windows.
* Fixed up some documentation about exceptions in ``serial.h``.
1.2.0 (2014-07-02) 1.2.0 (2014-07-02)
------------------ ------------------
* Removed vestigial ``read_cache_`` private member variable from Serial::Serial * Removed vestigial ``read_cache_`` private member variable from Serial::Serial

View File

@ -5,12 +5,14 @@ project(serial)
find_package(catkin REQUIRED) find_package(catkin REQUIRED)
if(APPLE) if(APPLE)
find_library(IOKIT_LIBRARY IOKit) find_library(IOKIT_LIBRARY IOKit)
find_library(FOUNDATION_LIBRARY Foundation) find_library(FOUNDATION_LIBRARY Foundation)
endif() endif()
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
# If Linux, add rt and pthread # If Linux, add rt and pthread
set(rt_LIBRARIES rt)
set(pthread_LIBRARIES pthread)
catkin_package( catkin_package(
LIBRARIES ${PROJECT_NAME} LIBRARIES ${PROJECT_NAME}
INCLUDE_DIRS include INCLUDE_DIRS include
@ -31,24 +33,27 @@ set(serial_SRCS
include/serial/v8stdint.h include/serial/v8stdint.h
) )
if(APPLE) if(APPLE)
# If OSX # If OSX
list(APPEND serial_SRCS src/impl/unix.cc) list(APPEND serial_SRCS src/impl/unix.cc)
list(APPEND serial_SRCS src/impl/list_ports/list_ports_osx.cc) list(APPEND serial_SRCS src/impl/list_ports/list_ports_osx.cc)
elseif(UNIX) elseif(UNIX)
# If unix # If unix
list(APPEND serial_SRCS src/impl/unix.cc) list(APPEND serial_SRCS src/impl/unix.cc)
list(APPEND serial_SRCS src/impl/list_ports/list_ports_linux.cc) list(APPEND serial_SRCS src/impl/list_ports/list_ports_linux.cc)
elseif() else()
# If windows # If windows
list(APPEND serial_SRCS src/impl/win.cc) list(APPEND serial_SRCS src/impl/win.cc)
list(APPEND serial_SRCS src/impl/list_ports/list_ports_win.cc)
endif() endif()
## Add serial library ## Add serial library
add_library(${PROJECT_NAME} ${serial_SRCS}) add_library(${PROJECT_NAME} ${serial_SRCS})
if(APPLE) if(APPLE)
target_link_libraries(${PROJECT_NAME} ${FOUNDATION_LIBRARY} ${IOKIT_LIBRARY}) target_link_libraries(${PROJECT_NAME} ${FOUNDATION_LIBRARY} ${IOKIT_LIBRARY})
elseif(UNIX) elseif(UNIX)
target_link_libraries(${PROJECT_NAME} rt pthread) target_link_libraries(${PROJECT_NAME} rt pthread)
else()
target_link_libraries(${PROJECT_NAME} setupapi)
endif() endif()
## Uncomment for example ## Uncomment for example
@ -63,6 +68,7 @@ include_directories(include)
install(TARGETS ${PROJECT_NAME} install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
) )
## Install headers ## Install headers

7
LICENSE Normal file
View File

@ -0,0 +1,7 @@
Copyright (c) 2012 William Woodall, John Harrison
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

@ -1,13 +1,36 @@
all: serial all: serial
CMAKE_FLAGS := -DCMAKE_INSTALL_PREFIX=/tmp/usr/local CMAKE_FLAGS := -DCMAKE_INSTALL_PREFIX=/tmp/usr/local
UNAME := $(shell uname -s)
install_deps:
ifeq ($(UNAME),Darwin)
brew tap ros/deps
brew update
brew outdated boost || brew upgrade boost || brew install boost
brew outdated python || brew upgrade python || brew install python
sudo -H python2 -m pip install -U pip setuptools
sudo -H python2 -m pip install --force-reinstall --no-deps -U pip
sudo -H python2 -m pip install rosinstall_generator wstool rosdep empy catkin_pkg
sudo -H rosdep init
rosdep update
mkdir catkin_ws
cd catkin_ws && rosinstall_generator catkin --rosdistro hydro --tar > catkin.rosinstall
cd catkin_ws && wstool init src catkin.rosinstall
cd catkin_ws && rosdep install --from-paths src --ignore-src -y
cd catkin_ws && python2 ./src/catkin/bin/catkin_make -DPYTHON_EXECUTABLE=`which python2` install
echo "source catkin_ws/install/setup.bash" > setup.bash
else
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu precise main" > /etc/apt/sources.list.d/ros-latest.list'
wget http://packages.ros.org/ros.key -O - | sudo apt-key add -
sudo apt-get update
sudo apt-get install ros-hydro-catkin libboost-dev
echo "source /opt/ros/hydro/setup.bash" > setup.bash
endif
install: install:
cd build && make install cd build && make install
uninstall:
cd build && make uninstall
serial: serial:
@mkdir -p build @mkdir -p build
cd build && cmake $(CMAKE_FLAGS) .. cd build && cmake $(CMAKE_FLAGS) ..

View File

@ -1,5 +1,7 @@
# Serial Communication Library # Serial Communication Library
[![Build Status](https://travis-ci.org/wjwwood/serial.svg?branch=master)](https://travis-ci.org/wjwwood/serial)*(Linux and OS X)* [![Build Status](https://ci.appveyor.com/api/projects/status/github/wjwwood/serial)](https://ci.appveyor.com/project/wjwwood/serial)*(Windows)*
This is a cross-platform library for interfacing with rs-232 serial like ports written in C++. It provides a modern C++ interface with a workflow designed to look and feel like PySerial, but with the speed and control provided by C++. This is a cross-platform library for interfacing with rs-232 serial like ports written in C++. It provides a modern C++ interface with a workflow designed to look and feel like PySerial, but with the speed and control provided by C++.
This library is in use in several robotics related projects and can be built and installed to the OS like most unix libraries with make and then sudo make install, but because it is a catkin project it can also be built along side other catkin projects in a catkin workspace. This library is in use in several robotics related projects and can be built and installed to the OS like most unix libraries with make and then sudo make install, but because it is a catkin project it can also be built along side other catkin projects in a catkin workspace.
@ -8,17 +10,22 @@ Serial is a class that provides the basic interface common to serial libraries (
### Documentation ### Documentation
Website: http://wjwwood.github.com/serial/ Website: http://wjwwood.github.io/serial/
API Documentation: http://wjwwood.github.com/serial/doc/1.1.0/index.html API Documentation: http://wjwwood.github.io/serial/doc/1.1.0/index.html
### Dependencies ### Dependencies
Required:
* [catkin](http://www.ros.org/wiki/catkin) - cmake and Python based buildsystem * [catkin](http://www.ros.org/wiki/catkin) - cmake and Python based buildsystem
* [cmake](http://www.cmake.org) - buildsystem * [cmake](http://www.cmake.org) - buildsystem
* [Python](http://www.python.org) - scripting language * [Python](http://www.python.org) - scripting language
* [empy](http://www.alcyone.com/pyos/empy/) - Python templating library * [empy](http://www.alcyone.com/pyos/empy/) - Python templating library
* [catkin_pkg](http://pypi.python.org/pypi/catkin_pkg/) - Runtime Python library for catkin * [catkin_pkg](http://pypi.python.org/pypi/catkin_pkg/) - Runtime Python library for catkin
Optional (for documentation):
* [Doxygen](http://www.doxygen.org/) - Documentation generation tool
* [graphviz](http://www.graphviz.org/) - Graph visualization software
### Install ### Install
@ -36,27 +43,15 @@ Build and run the tests:
Build the documentation: Build the documentation:
make docs make doc
Install: Install:
make install make install
Uninstall:
make uninstall
### License ### License
The MIT License [The MIT License](LICENSE)
Copyright (c) 2012 William Woodall, John Harrison
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.
### Authors ### Authors

File diff suppressed because it is too large Load Diff

View File

@ -55,10 +55,4 @@ To install simply:
sudo make install sudo make install
</pre> </pre>
To uninstall simply:
<pre>
sudo make uninstall
</pre>
*/ */

View File

@ -66,7 +66,9 @@ typedef enum {
typedef enum { typedef enum {
parity_none = 0, parity_none = 0,
parity_odd = 1, parity_odd = 1,
parity_even = 2 parity_even = 2,
parity_mark = 3,
parity_space = 4
} parity_t; } parity_t;
/*! /*!
@ -255,6 +257,9 @@ public:
* *
* \return A size_t representing the number of bytes read as a result of the * \return A size_t representing the number of bytes read as a result of the
* call to read. * call to read.
*
* \throw serial::PortNotOpenedException
* \throw serial::SerialException
*/ */
size_t size_t
read (uint8_t *buffer, size_t size); read (uint8_t *buffer, size_t size);
@ -266,6 +271,9 @@ public:
* *
* \return A size_t representing the number of bytes read as a result of the * \return A size_t representing the number of bytes read as a result of the
* call to read. * call to read.
*
* \throw serial::PortNotOpenedException
* \throw serial::SerialException
*/ */
size_t size_t
read (std::vector<uint8_t> &buffer, size_t size = 1); read (std::vector<uint8_t> &buffer, size_t size = 1);
@ -277,6 +285,9 @@ public:
* *
* \return A size_t representing the number of bytes read as a result of the * \return A size_t representing the number of bytes read as a result of the
* call to read. * call to read.
*
* \throw serial::PortNotOpenedException
* \throw serial::SerialException
*/ */
size_t size_t
read (std::string &buffer, size_t size = 1); read (std::string &buffer, size_t size = 1);
@ -287,6 +298,9 @@ public:
* \param size A size_t defining how many bytes to be read. * \param size A size_t defining how many bytes to be read.
* *
* \return A std::string containing the data read from the port. * \return A std::string containing the data read from the port.
*
* \throw serial::PortNotOpenedException
* \throw serial::SerialException
*/ */
std::string std::string
read (size_t size = 1); read (size_t size = 1);
@ -300,6 +314,9 @@ public:
* \param eol A string to match against for the EOL. * \param eol A string to match against for the EOL.
* *
* \return A size_t representing the number of bytes read. * \return A size_t representing the number of bytes read.
*
* \throw serial::PortNotOpenedException
* \throw serial::SerialException
*/ */
size_t size_t
readline (std::string &buffer, size_t size = 65536, std::string eol = "\n"); readline (std::string &buffer, size_t size = 65536, std::string eol = "\n");
@ -312,6 +329,9 @@ public:
* \param eol A string to match against for the EOL. * \param eol A string to match against for the EOL.
* *
* \return A std::string containing the line. * \return A std::string containing the line.
*
* \throw serial::PortNotOpenedException
* \throw serial::SerialException
*/ */
std::string std::string
readline (size_t size = 65536, std::string eol = "\n"); readline (size_t size = 65536, std::string eol = "\n");
@ -326,6 +346,9 @@ public:
* \param eol A string to match against for the EOL. * \param eol A string to match against for the EOL.
* *
* \return A vector<string> containing the lines. * \return A vector<string> containing the lines.
*
* \throw serial::PortNotOpenedException
* \throw serial::SerialException
*/ */
std::vector<std::string> std::vector<std::string>
readlines (size_t size = 65536, std::string eol = "\n"); readlines (size_t size = 65536, std::string eol = "\n");
@ -340,6 +363,10 @@ public:
* *
* \return A size_t representing the number of bytes actually written to * \return A size_t representing the number of bytes actually written to
* the serial port. * the serial port.
*
* \throw serial::PortNotOpenedException
* \throw serial::SerialException
* \throw serial::IOException
*/ */
size_t size_t
write (const uint8_t *data, size_t size); write (const uint8_t *data, size_t size);
@ -351,6 +378,10 @@ public:
* *
* \return A size_t representing the number of bytes actually written to * \return A size_t representing the number of bytes actually written to
* the serial port. * the serial port.
*
* \throw serial::PortNotOpenedException
* \throw serial::SerialException
* \throw serial::IOException
*/ */
size_t size_t
write (const std::vector<uint8_t> &data); write (const std::vector<uint8_t> &data);
@ -362,6 +393,10 @@ public:
* *
* \return A size_t representing the number of bytes actually written to * \return A size_t representing the number of bytes actually written to
* the serial port. * the serial port.
*
* \throw serial::PortNotOpenedException
* \throw serial::SerialException
* \throw serial::IOException
*/ */
size_t size_t
write (const std::string &data); write (const std::string &data);
@ -372,7 +407,7 @@ public:
* serial port, which would be something like 'COM1' on Windows and * serial port, which would be something like 'COM1' on Windows and
* '/dev/ttyS0' on Linux. * '/dev/ttyS0' on Linux.
* *
* \throw InvalidConfigurationException * \throw std::invalid_argument
*/ */
void void
setPort (const std::string &port); setPort (const std::string &port);
@ -381,7 +416,7 @@ public:
* *
* \see Serial::setPort * \see Serial::setPort
* *
* \throw InvalidConfigurationException * \throw std::invalid_argument
*/ */
std::string std::string
getPort () const; getPort () const;
@ -415,6 +450,8 @@ public:
* reading or writing is complete, when a timeout occurs, or when an * reading or writing is complete, when a timeout occurs, or when an
* exception occurs. * exception occurs.
* *
* A timeout of 0 enables non-blocking mode.
*
* \param timeout A serial::Timeout struct containing the inter byte * \param timeout A serial::Timeout struct containing the inter byte
* timeout, and the read and write timeout constants and multipliers. * timeout, and the read and write timeout constants and multipliers.
* *
@ -451,11 +488,11 @@ public:
* 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000, * 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000,
* 57600, 115200 * 57600, 115200
* Some other baudrates that are supported by some comports: * Some other baudrates that are supported by some comports:
* 128000, 153600, 230400, 256000, 460800, 921600 * 128000, 153600, 230400, 256000, 460800, 500000, 921600
* *
* \param baudrate An integer that sets the baud rate for the serial port. * \param baudrate An integer that sets the baud rate for the serial port.
* *
* \throw InvalidConfigurationException * \throw std::invalid_argument
*/ */
void void
setBaudrate (uint32_t baudrate); setBaudrate (uint32_t baudrate);
@ -466,7 +503,7 @@ public:
* *
* \see Serial::setBaudrate * \see Serial::setBaudrate
* *
* \throw InvalidConfigurationException * \throw std::invalid_argument
*/ */
uint32_t uint32_t
getBaudrate () const; getBaudrate () const;
@ -477,7 +514,7 @@ public:
* default is eightbits, possible values are: fivebits, sixbits, sevenbits, * default is eightbits, possible values are: fivebits, sixbits, sevenbits,
* eightbits * eightbits
* *
* \throw InvalidConfigurationException * \throw std::invalid_argument
*/ */
void void
setBytesize (bytesize_t bytesize); setBytesize (bytesize_t bytesize);
@ -486,7 +523,7 @@ public:
* *
* \see Serial::setBytesize * \see Serial::setBytesize
* *
* \throw InvalidConfigurationException * \throw std::invalid_argument
*/ */
bytesize_t bytesize_t
getBytesize () const; getBytesize () const;
@ -496,7 +533,7 @@ public:
* \param parity Method of parity, default is parity_none, possible values * \param parity Method of parity, default is parity_none, possible values
* are: parity_none, parity_odd, parity_even * are: parity_none, parity_odd, parity_even
* *
* \throw InvalidConfigurationException * \throw std::invalid_argument
*/ */
void void
setParity (parity_t parity); setParity (parity_t parity);
@ -505,7 +542,7 @@ public:
* *
* \see Serial::setParity * \see Serial::setParity
* *
* \throw InvalidConfigurationException * \throw std::invalid_argument
*/ */
parity_t parity_t
getParity () const; getParity () const;
@ -515,7 +552,7 @@ public:
* \param stopbits Number of stop bits used, default is stopbits_one, * \param stopbits Number of stop bits used, default is stopbits_one,
* possible values are: stopbits_one, stopbits_one_point_five, stopbits_two * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two
* *
* \throw InvalidConfigurationException * \throw std::invalid_argument
*/ */
void void
setStopbits (stopbits_t stopbits); setStopbits (stopbits_t stopbits);
@ -524,7 +561,7 @@ public:
* *
* \see Serial::setStopbits * \see Serial::setStopbits
* *
* \throw InvalidConfigurationException * \throw std::invalid_argument
*/ */
stopbits_t stopbits_t
getStopbits () const; getStopbits () const;
@ -535,7 +572,7 @@ public:
* possible values are: flowcontrol_none, flowcontrol_software, * possible values are: flowcontrol_none, flowcontrol_software,
* flowcontrol_hardware * flowcontrol_hardware
* *
* \throw InvalidConfigurationException * \throw std::invalid_argument
*/ */
void void
setFlowcontrol (flowcontrol_t flowcontrol); setFlowcontrol (flowcontrol_t flowcontrol);
@ -544,7 +581,7 @@ public:
* *
* \see Serial::setFlowcontrol * \see Serial::setFlowcontrol
* *
* \throw InvalidConfigurationException * \throw std::invalid_argument
*/ */
flowcontrol_t flowcontrol_t
getFlowcontrol () const; getFlowcontrol () const;
@ -682,7 +719,7 @@ public:
virtual ~IOException() throw() {} virtual ~IOException() throw() {}
IOException (const IOException& other) : line_(other.line_), e_what_(other.e_what_), errno_(other.errno_) {} IOException (const IOException& other) : line_(other.line_), e_what_(other.e_what_), errno_(other.errno_) {}
int getErrorNumber () { return errno_; } int getErrorNumber () const { return errno_; }
virtual const char* what () const throw () { virtual const char* what () const throw () {
return e_what_.c_str(); return e_what_.c_str();

View File

@ -1,9 +1,11 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<package> <package>
<name>serial</name> <name>serial</name>
<version>1.2.0</version> <version>1.2.1</version>
<description> <description>
Serial is a cross-platform, simple to use library for using serial ports on computers. This library provides a C++, object oriented interface for interacting with RS-232 like devices on Linux and Windows. Serial is a cross-platform, simple to use library for using serial ports on computers.
This library provides a C++, object oriented interface for interacting with RS-232
like devices on Linux and Windows.
</description> </description>
<maintainer email="william@osrfoundation.org">William Woodall</maintainer> <maintainer email="william@osrfoundation.org">William Woodall</maintainer>
@ -19,6 +21,4 @@
<buildtool_depend>catkin</buildtool_depend> <buildtool_depend>catkin</buildtool_depend>
<test_depend>boost</test_depend>
</package> </package>

View File

@ -11,9 +11,12 @@
{ {
"sublimeclang_options": "sublimeclang_options":
[ [
"-I/usr/include", "-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
"-I/usr/local/include", "-I/usr/local/include",
"-I${folder:${project_path:serial.sublime-project}}/include" "-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/9.0.0/include",
"-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
"-I/usr/include",
"-I${folder:${project_path:serial.sublime-project}}/include",
] ]
} }
} }

View File

@ -305,6 +305,7 @@ serial::list_ports()
search_globs.push_back("/dev/ttyUSB*"); search_globs.push_back("/dev/ttyUSB*");
search_globs.push_back("/dev/tty.*"); search_globs.push_back("/dev/tty.*");
search_globs.push_back("/dev/cu.*"); search_globs.push_back("/dev/cu.*");
search_globs.push_back("/dev/rfcomm*");
vector<string> devices_found = glob( search_globs ); vector<string> devices_found = glob( search_globs );
@ -324,7 +325,7 @@ serial::list_ports()
device_entry.port = device; device_entry.port = device;
device_entry.description = friendly_name; device_entry.description = friendly_name;
device_entry.hardware_id = hardware_id; device_entry.hardware_id = hardware_id;
results.push_back( device_entry ); results.push_back( device_entry );
} }

View File

@ -36,9 +36,9 @@ cfstring_to_string( CFStringRef cfstring )
if( cfstring ) if( cfstring )
{ {
Boolean success = CFStringGetCString( cfstring, Boolean success = CFStringGetCString( cfstring,
cstring, cstring,
sizeof(cstring), sizeof(cstring),
kCFStringEncodingASCII ); kCFStringEncodingASCII );
if( success ) if( success )
@ -106,7 +106,7 @@ get_parent_iousb_device( io_object_t& serial_port )
result = 0; result = 0;
break; break;
} }
device = parent; device = parent;
name = get_class_name(device); name = get_class_name(device);
@ -125,15 +125,15 @@ get_string_property( io_object_t& device, const char* property )
if( device ) if( device )
{ {
CFStringRef property_as_cfstring = CFStringCreateWithCString ( CFStringRef property_as_cfstring = CFStringCreateWithCString (
kCFAllocatorDefault, kCFAllocatorDefault,
property, property,
kCFStringEncodingASCII ); kCFStringEncodingASCII );
CFTypeRef name_as_cfstring = IORegistryEntryCreateCFProperty( CFTypeRef name_as_cfstring = IORegistryEntryCreateCFProperty(
device, device,
property_as_cfstring, property_as_cfstring,
kCFAllocatorDefault, kCFAllocatorDefault,
0 ); 0 );
if( name_as_cfstring ) if( name_as_cfstring )
@ -142,12 +142,12 @@ get_string_property( io_object_t& device, const char* property )
property_name = cfstring_to_string( static_cast<CFStringRef>(name_as_cfstring) ); property_name = cfstring_to_string( static_cast<CFStringRef>(name_as_cfstring) );
CFRelease(name_as_cfstring); CFRelease(name_as_cfstring);
} }
if(property_as_cfstring) if(property_as_cfstring)
CFRelease(property_as_cfstring); CFRelease(property_as_cfstring);
} }
return property_name; return property_name;
} }
@ -158,14 +158,14 @@ get_int_property( io_object_t& device, const char* property )
if( device ) if( device )
{ {
CFStringRef property_as_cfstring = CFStringCreateWithCString ( CFStringRef property_as_cfstring = CFStringCreateWithCString (
kCFAllocatorDefault, kCFAllocatorDefault,
property, property,
kCFStringEncodingASCII ); kCFStringEncodingASCII );
CFTypeRef number = IORegistryEntryCreateCFProperty( device, CFTypeRef number = IORegistryEntryCreateCFProperty( device,
property_as_cfstring, property_as_cfstring,
kCFAllocatorDefault, kCFAllocatorDefault,
0 ); 0 );
if(property_as_cfstring) if(property_as_cfstring)
@ -175,8 +175,8 @@ get_int_property( io_object_t& device, const char* property )
{ {
if( CFGetTypeID(number) == CFNumberGetTypeID() ) if( CFGetTypeID(number) == CFNumberGetTypeID() )
{ {
bool success = CFNumberGetValue( static_cast<CFNumberRef>(number), bool success = CFNumberGetValue( static_cast<CFNumberRef>(number),
kCFNumberSInt16Type, kCFNumberSInt16Type,
&result ); &result );
if( !success ) if( !success )
@ -187,7 +187,7 @@ get_int_property( io_object_t& device, const char* property )
} }
} }
return result; return result;
} }
@ -198,7 +198,7 @@ string rtrim(const string& str)
string whitespace = " \t\f\v\n\r"; string whitespace = " \t\f\v\n\r";
std::size_t found = result.find_last_not_of(whitespace); std::size_t found = result.find_last_not_of(whitespace);
if (found != std::string::npos) if (found != std::string::npos)
result.erase(found+1); result.erase(found+1);
else else
@ -244,7 +244,7 @@ serial::list_ports(void)
if( device_path.empty() ) if( device_path.empty() )
continue; continue;
PortInfo port_info; PortInfo port_info;
port_info.port = device_path; port_info.port = device_path;
port_info.description = "n/a"; port_info.description = "n/a";
@ -267,18 +267,19 @@ serial::list_ports(void)
if(serial_number.empty()) if(serial_number.empty())
serial_number = "None"; serial_number = "None";
int ret = snprintf( cstring, HARDWARE_ID_STRING_LENGTH, "USB VID:PID=%04x:%04x SNR=%s", int ret = snprintf( cstring, HARDWARE_ID_STRING_LENGTH, "USB VID:PID=%04x:%04x SNR=%s",
vendor_id, vendor_id,
product_id, product_id,
serial_number.c_str() ); serial_number.c_str() );
if( (ret >= 0) && (ret < HARDWARE_ID_STRING_LENGTH) ) if( (ret >= 0) && (ret < HARDWARE_ID_STRING_LENGTH) )
port_info.hardware_id = cstring; port_info.hardware_id = cstring;
} }
devices_found.push_back(port_info); devices_found.push_back(port_info);
} }
IOObjectRelease(serial_port_iterator);
return devices_found; return devices_found;
} }

View File

@ -8,8 +8,10 @@
*/ */
#include "serial/serial.h" #include "serial/serial.h"
#include <tchar.h>
#include <windows.h> #include <windows.h>
#include <SetupAPI.h> #include <setupapi.h>
#include <initguid.h>
#include <devguid.h> #include <devguid.h>
#include <cstring> #include <cstring>
@ -21,10 +23,19 @@ static const DWORD port_name_max_length = 256;
static const DWORD friendly_name_max_length = 256; static const DWORD friendly_name_max_length = 256;
static const DWORD hardware_id_max_length = 256; static const DWORD hardware_id_max_length = 256;
// Convert a wide Unicode string to an UTF8 string
std::string utf8_encode(const std::wstring &wstr)
{
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
std::string strTo( size_needed, 0 );
WideCharToMultiByte (CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
return strTo;
}
vector<PortInfo> vector<PortInfo>
serial::list_ports() serial::list_ports()
{ {
decltype( serial::list_ports() ) devices_found; vector<PortInfo> devices_found;
HDEVINFO device_info_set = SetupDiGetClassDevs( HDEVINFO device_info_set = SetupDiGetClassDevs(
(const GUID *) &GUID_DEVCLASS_PORTS, (const GUID *) &GUID_DEVCLASS_PORTS,
@ -51,16 +62,16 @@ serial::list_ports()
DIREG_DEV, DIREG_DEV,
KEY_READ); KEY_READ);
char port_name[port_name_max_length]; TCHAR port_name[port_name_max_length];
DWORD port_name_length = port_name_max_length; DWORD port_name_length = port_name_max_length;
LONG return_code = RegQueryValueEx( LONG return_code = RegQueryValueEx(
hkey, hkey,
"PortName", _T("PortName"),
NULL,
NULL, NULL,
(LPBYTE)port_name, NULL,
&port_name_length); (LPBYTE)port_name,
&port_name_length);
RegCloseKey(hkey); RegCloseKey(hkey);
@ -74,22 +85,22 @@ serial::list_ports()
// Ignore parallel ports // Ignore parallel ports
if(strstr(port_name, "LPT") != NULL) if(_tcsstr(port_name, _T("LPT")) != NULL)
continue; continue;
// Get port friendly name // Get port friendly name
char friendly_name[friendly_name_max_length]; TCHAR friendly_name[friendly_name_max_length];
DWORD friendly_name_actual_length = 0; DWORD friendly_name_actual_length = 0;
BOOL got_friendly_name = SetupDiGetDeviceRegistryProperty( BOOL got_friendly_name = SetupDiGetDeviceRegistryProperty(
device_info_set, device_info_set,
&device_info_data, &device_info_data,
SPDRP_FRIENDLYNAME, SPDRP_FRIENDLYNAME,
NULL, NULL,
(PBYTE)friendly_name, (PBYTE)friendly_name,
friendly_name_max_length, friendly_name_max_length,
&friendly_name_actual_length); &friendly_name_actual_length);
if(got_friendly_name == TRUE && friendly_name_actual_length > 0) if(got_friendly_name == TRUE && friendly_name_actual_length > 0)
friendly_name[friendly_name_actual_length-1] = '\0'; friendly_name[friendly_name_actual_length-1] = '\0';
@ -98,27 +109,37 @@ serial::list_ports()
// Get hardware ID // Get hardware ID
char hardware_id[hardware_id_max_length]; TCHAR hardware_id[hardware_id_max_length];
DWORD hardware_id_actual_length = 0; DWORD hardware_id_actual_length = 0;
BOOL got_hardware_id = SetupDiGetDeviceRegistryProperty( BOOL got_hardware_id = SetupDiGetDeviceRegistryProperty(
device_info_set, device_info_set,
&device_info_data, &device_info_data,
SPDRP_HARDWAREID, SPDRP_HARDWAREID,
NULL, NULL,
(PBYTE)hardware_id, (PBYTE)hardware_id,
hardware_id_max_length, hardware_id_max_length,
&hardware_id_actual_length); &hardware_id_actual_length);
if(got_hardware_id == TRUE && hardware_id_actual_length > 0) if(got_hardware_id == TRUE && hardware_id_actual_length > 0)
hardware_id[hardware_id_actual_length-1] = '\0'; hardware_id[hardware_id_actual_length-1] = '\0';
else else
hardware_id[0] = '\0'; hardware_id[0] = '\0';
#ifdef UNICODE
std::string portName = utf8_encode(port_name);
std::string friendlyName = utf8_encode(friendly_name);
std::string hardwareId = utf8_encode(hardware_id);
#else
std::string portName = port_name;
std::string friendlyName = friendly_name;
std::string hardwareId = hardware_id;
#endif
PortInfo port_entry; PortInfo port_entry;
port_entry.port = port_name; port_entry.port = portName;
port_entry.description = friendly_name; port_entry.description = friendlyName;
port_entry.hardware_id = hardware_id; port_entry.hardware_id = hardwareId;
devices_found.push_back(port_entry); devices_found.push_back(port_entry);
} }

View File

@ -27,6 +27,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
#ifdef __MACH__ #ifdef __MACH__
#include <AvailabilityMacros.h>
#include <mach/clock.h> #include <mach/clock.h>
#include <mach/mach.h> #include <mach/mach.h>
#endif #endif
@ -61,7 +62,7 @@ MillisecondTimer::MillisecondTimer (const uint32_t millis)
int64_t tv_nsec = expiry.tv_nsec + (millis * 1e6); int64_t tv_nsec = expiry.tv_nsec + (millis * 1e6);
if (tv_nsec >= 1e9) { if (tv_nsec >= 1e9) {
int64_t sec_diff = tv_nsec / static_cast<int> (1e9); int64_t sec_diff = tv_nsec / static_cast<int> (1e9);
expiry.tv_nsec = tv_nsec - static_cast<int> (1e9 * sec_diff); expiry.tv_nsec = tv_nsec % static_cast<int>(1e9);
expiry.tv_sec += sec_diff; expiry.tv_sec += sec_diff;
} else { } else {
expiry.tv_nsec = tv_nsec; expiry.tv_nsec = tv_nsec;
@ -84,13 +85,13 @@ MillisecondTimer::timespec_now ()
# ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time # ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
clock_serv_t cclock; clock_serv_t cclock;
mach_timespec_t mts; mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
clock_get_time(cclock, &mts); clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock); mach_port_deallocate(mach_task_self(), cclock);
time.tv_sec = mts.tv_sec; time.tv_sec = mts.tv_sec;
time.tv_nsec = mts.tv_nsec; time.tv_nsec = mts.tv_nsec;
# else # else
clock_gettime(CLOCK_REALTIME, &time); clock_gettime(CLOCK_MONOTONIC, &time);
# endif # endif
return time; return time;
} }
@ -268,6 +269,12 @@ Serial::SerialImpl::reconfigurePort ()
#ifdef B460800 #ifdef B460800
case 460800: baud = B460800; break; case 460800: baud = B460800; break;
#endif #endif
#ifdef B500000
case 500000: baud = B500000; break;
#endif
#ifdef B576000
case 576000: baud = B576000; break;
#endif
#ifdef B921600 #ifdef B921600
case 921600: baud = B921600; break; case 921600: baud = B921600; break;
#endif #endif
@ -297,36 +304,6 @@ Serial::SerialImpl::reconfigurePort ()
#endif #endif
default: default:
custom_baud = true; custom_baud = true;
// OS X support
#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
// Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates
// other than those specified by POSIX. The driver for the underlying serial hardware
// ultimately determines which baud rates can be used. This ioctl sets both the input
// and output speed.
speed_t new_baud = static_cast<speed_t> (baudrate_);
if (-1 == ioctl (fd_, IOSSIOSPEED, &new_baud, 1)) {
THROW (IOException, errno);
}
// Linux Support
#elif defined(__linux__) && defined (TIOCSSERIAL)
struct serial_struct ser;
if (-1 == ioctl (fd_, TIOCGSERIAL, &ser)) {
THROW (IOException, errno);
}
// set custom divisor
ser.custom_divisor = ser.baud_base / static_cast<int> (baudrate_);
// update flags
ser.flags &= ~ASYNC_SPD_MASK;
ser.flags |= ASYNC_SPD_CUST;
if (-1 == ioctl (fd_, TIOCSSERIAL, &ser)) {
THROW (IOException, errno);
}
#else
throw invalid_argument ("OS does not currently support custom bauds");
#endif
} }
if (custom_baud == false) { if (custom_baud == false) {
#ifdef _BSD_SOURCE #ifdef _BSD_SOURCE
@ -368,7 +345,22 @@ Serial::SerialImpl::reconfigurePort ()
options.c_cflag |= (PARENB); options.c_cflag |= (PARENB);
} else if (parity_ == parity_odd) { } else if (parity_ == parity_odd) {
options.c_cflag |= (PARENB | PARODD); options.c_cflag |= (PARENB | PARODD);
} else { }
#ifdef CMSPAR
else if (parity_ == parity_mark) {
options.c_cflag |= (PARENB | CMSPAR | PARODD);
}
else if (parity_ == parity_space) {
options.c_cflag |= (PARENB | CMSPAR);
options.c_cflag &= (tcflag_t) ~(PARODD);
}
#else
// CMSPAR is not defined on OSX. So do not support mark or space parity.
else if (parity_ == parity_mark || parity_ == parity_space) {
throw invalid_argument ("OS does not support mark or space parity");
}
#endif // ifdef CMSPAR
else {
throw invalid_argument ("invalid parity"); throw invalid_argument ("invalid parity");
} }
// setup flow control // setup flow control
@ -421,6 +413,41 @@ Serial::SerialImpl::reconfigurePort ()
// activate settings // activate settings
::tcsetattr (fd_, TCSANOW, &options); ::tcsetattr (fd_, TCSANOW, &options);
// apply custom baud rate, if any
if (custom_baud == true) {
// OS X support
#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
// Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates
// other than those specified by POSIX. The driver for the underlying serial hardware
// ultimately determines which baud rates can be used. This ioctl sets both the input
// and output speed.
speed_t new_baud = static_cast<speed_t> (baudrate_);
// PySerial uses IOSSIOSPEED=0x80045402
if (-1 == ioctl (fd_, IOSSIOSPEED, &new_baud, 1)) {
THROW (IOException, errno);
}
// Linux Support
#elif defined(__linux__) && defined (TIOCSSERIAL)
struct serial_struct ser;
if (-1 == ioctl (fd_, TIOCGSERIAL, &ser)) {
THROW (IOException, errno);
}
// set custom divisor
ser.custom_divisor = ser.baud_base / static_cast<int> (baudrate_);
// update flags
ser.flags &= ~ASYNC_SPD_MASK;
ser.flags |= ASYNC_SPD_CUST;
if (-1 == ioctl (fd_, TIOCSSERIAL, &ser)) {
THROW (IOException, errno);
}
#else
throw invalid_argument ("OS does not currently support custom bauds");
#endif
}
// Update byte_time_ based on the new settings. // Update byte_time_ based on the new settings.
uint32_t bit_time_ns = 1e9 / baudrate_; uint32_t bit_time_ns = 1e9 / baudrate_;
byte_time_ns_ = bit_time_ns * (1 + bytesize_ + parity_ + stopbits_); byte_time_ns_ = bit_time_ns * (1 + bytesize_ + parity_ + stopbits_);
@ -503,7 +530,7 @@ Serial::SerialImpl::waitReadable (uint32_t timeout)
void void
Serial::SerialImpl::waitByteTimes (size_t count) Serial::SerialImpl::waitByteTimes (size_t count)
{ {
timespec wait_time = { 0, byte_time_ns_ * count }; timespec wait_time = { 0, static_cast<long>(byte_time_ns_ * count)};
pselect (0, NULL, NULL, NULL, &wait_time, NULL); pselect (0, NULL, NULL, NULL, &wait_time, NULL);
} }
@ -598,12 +625,17 @@ Serial::SerialImpl::write (const uint8_t *data, size_t length)
total_timeout_ms += timeout_.write_timeout_multiplier * static_cast<long> (length); total_timeout_ms += timeout_.write_timeout_multiplier * static_cast<long> (length);
MillisecondTimer total_timeout(total_timeout_ms); MillisecondTimer total_timeout(total_timeout_ms);
bool first_iteration = true;
while (bytes_written < length) { while (bytes_written < length) {
int64_t timeout_remaining_ms = total_timeout.remaining(); int64_t timeout_remaining_ms = total_timeout.remaining();
if (timeout_remaining_ms <= 0) { // Only consider the timeout if it's not the first iteration of the loop
// otherwise a timeout of 0 won't be allowed through
if (!first_iteration && (timeout_remaining_ms <= 0)) {
// Timed out // Timed out
break; break;
} }
first_iteration = false;
timespec timeout(timespec_from_ms(timeout_remaining_ms)); timespec timeout(timespec_from_ms(timeout_remaining_ms));
FD_ZERO (&writefds); FD_ZERO (&writefds);
@ -633,14 +665,27 @@ Serial::SerialImpl::write (const uint8_t *data, size_t length)
// This will write some // This will write some
ssize_t bytes_written_now = ssize_t bytes_written_now =
::write (fd_, data + bytes_written, length - bytes_written); ::write (fd_, data + bytes_written, length - bytes_written);
// even though pselect returned readiness the call might still be
// interrupted. In that case simply retry.
if (bytes_written_now == -1 && errno == EINTR) {
continue;
}
// write should always return some data as select reported it was // write should always return some data as select reported it was
// ready to write when we get to this point. // ready to write when we get to this point.
if (bytes_written_now < 1) { if (bytes_written_now < 1) {
// Disconnected devices, at least on Linux, show the // Disconnected devices, at least on Linux, show the
// behavior that they are always ready to write immediately // behavior that they are always ready to write immediately
// but writing returns nothing. // but writing returns nothing.
throw SerialException ("device reports readiness to write but " std::stringstream strs;
"returned no data (device disconnected?)"); strs << "device reports readiness to write but "
"returned no data (device disconnected?)";
strs << " errno=" << errno;
strs << " bytes_written_now= " << bytes_written_now;
strs << " bytes_written=" << bytes_written;
strs << " length=" << length;
throw SerialException(strs.str().c_str());
} }
// Update bytes_written // Update bytes_written
bytes_written += static_cast<size_t> (bytes_written_now); bytes_written += static_cast<size_t> (bytes_written_now);

View File

@ -20,6 +20,16 @@ using serial::SerialException;
using serial::PortNotOpenedException; using serial::PortNotOpenedException;
using serial::IOException; using serial::IOException;
inline wstring
_prefix_port_if_needed(const wstring &input)
{
static wstring windows_com_port_prefix = L"\\\\.\\";
if (input.compare(0, windows_com_port_prefix.size(), windows_com_port_prefix) != 0)
{
return windows_com_port_prefix + input;
}
return input;
}
Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
bytesize_t bytesize, bytesize_t bytesize,
@ -29,10 +39,10 @@ Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
baudrate_ (baudrate), parity_ (parity), baudrate_ (baudrate), parity_ (parity),
bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol)
{ {
read_mutex = CreateMutex(NULL, false, NULL);
write_mutex = CreateMutex(NULL, false, NULL);
if (port_.empty () == false) if (port_.empty () == false)
open (); open ();
read_mutex = CreateMutex(NULL, false, NULL);
write_mutex = CreateMutex(NULL, false, NULL);
} }
Serial::SerialImpl::~SerialImpl () Serial::SerialImpl::~SerialImpl ()
@ -52,7 +62,9 @@ Serial::SerialImpl::open ()
throw SerialException ("Serial port already open."); throw SerialException ("Serial port already open.");
} }
LPCWSTR lp_port = port_.c_str(); // See: https://github.com/wjwwood/serial/issues/84
wstring port_with_prefix = _prefix_port_if_needed(port_);
LPCWSTR lp_port = port_with_prefix.c_str();
fd_ = CreateFileW(lp_port, fd_ = CreateFileW(lp_port,
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
0, 0,
@ -62,15 +74,15 @@ Serial::SerialImpl::open ()
0); 0);
if (fd_ == INVALID_HANDLE_VALUE) { if (fd_ == INVALID_HANDLE_VALUE) {
DWORD errno_ = GetLastError(); DWORD create_file_err = GetLastError();
stringstream ss; stringstream ss;
switch (errno_) { switch (create_file_err) {
case ERROR_FILE_NOT_FOUND: case ERROR_FILE_NOT_FOUND:
// Use this->getPort to convert to a std::string // Use this->getPort to convert to a std::string
ss << "Specified port, " << this->getPort() << ", does not exist."; ss << "Specified port, " << this->getPort() << ", does not exist.";
THROW (IOException, ss.str().c_str()); THROW (IOException, ss.str().c_str());
default: default:
ss << "Unknown error opening the serial port: " << errno; ss << "Unknown error opening the serial port: " << create_file_err;
THROW (IOException, ss.str().c_str()); THROW (IOException, ss.str().c_str());
} }
} }
@ -216,6 +228,10 @@ Serial::SerialImpl::reconfigurePort ()
dcbSerialParams.Parity = EVENPARITY; dcbSerialParams.Parity = EVENPARITY;
} else if (parity_ == parity_odd) { } else if (parity_ == parity_odd) {
dcbSerialParams.Parity = ODDPARITY; dcbSerialParams.Parity = ODDPARITY;
} else if (parity_ == parity_mark) {
dcbSerialParams.Parity = MARKPARITY;
} else if (parity_ == parity_space) {
dcbSerialParams.Parity = SPACEPARITY;
} else { } else {
throw invalid_argument ("invalid parity"); throw invalid_argument ("invalid parity");
} }
@ -223,25 +239,26 @@ Serial::SerialImpl::reconfigurePort ()
// setup flowcontrol // setup flowcontrol
if (flowcontrol_ == flowcontrol_none) { if (flowcontrol_ == flowcontrol_none) {
dcbSerialParams.fOutxCtsFlow = false; dcbSerialParams.fOutxCtsFlow = false;
dcbSerialParams.fRtsControl = 0x00; dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE;
dcbSerialParams.fOutX = false; dcbSerialParams.fOutX = false;
dcbSerialParams.fInX = false; dcbSerialParams.fInX = false;
} }
if (flowcontrol_ == flowcontrol_software) { if (flowcontrol_ == flowcontrol_software) {
dcbSerialParams.fOutxCtsFlow = false; dcbSerialParams.fOutxCtsFlow = false;
dcbSerialParams.fRtsControl = 0x00; dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE;
dcbSerialParams.fOutX = true; dcbSerialParams.fOutX = true;
dcbSerialParams.fInX = true; dcbSerialParams.fInX = true;
} }
if (flowcontrol_ == flowcontrol_hardware) { if (flowcontrol_ == flowcontrol_hardware) {
dcbSerialParams.fOutxCtsFlow = true; dcbSerialParams.fOutxCtsFlow = true;
dcbSerialParams.fRtsControl = 0x03; dcbSerialParams.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcbSerialParams.fOutX = false; dcbSerialParams.fOutX = false;
dcbSerialParams.fInX = false; dcbSerialParams.fInX = false;
} }
// activate settings // activate settings
if (!SetCommState(fd_, &dcbSerialParams)){ if (!SetCommState(fd_, &dcbSerialParams)){
CloseHandle(fd_);
THROW (IOException, "Error setting serial port settings."); THROW (IOException, "Error setting serial port settings.");
} }
@ -298,14 +315,14 @@ Serial::SerialImpl::available ()
} }
bool bool
Serial::SerialImpl::waitReadable (uint32_t timeout) Serial::SerialImpl::waitReadable (uint32_t /*timeout*/)
{ {
THROW (IOException, "waitReadable is not implemented on Windows."); THROW (IOException, "waitReadable is not implemented on Windows.");
return false; return false;
} }
void void
Serial::SerialImpl::waitByteTimes (size_t count) Serial::SerialImpl::waitByteTimes (size_t /*count*/)
{ {
THROW (IOException, "waitByteTimes is not implemented on Windows."); THROW (IOException, "waitByteTimes is not implemented on Windows.");
} }
@ -317,7 +334,7 @@ Serial::SerialImpl::read (uint8_t *buf, size_t size)
throw PortNotOpenedException ("Serial::read"); throw PortNotOpenedException ("Serial::read");
} }
DWORD bytes_read; DWORD bytes_read;
if (!ReadFile(fd_, buf, size, &bytes_read, NULL)) { if (!ReadFile(fd_, buf, static_cast<DWORD>(size), &bytes_read, NULL)) {
stringstream ss; stringstream ss;
ss << "Error while reading from the serial port: " << GetLastError(); ss << "Error while reading from the serial port: " << GetLastError();
THROW (IOException, ss.str().c_str()); THROW (IOException, ss.str().c_str());
@ -332,7 +349,7 @@ Serial::SerialImpl::write (const uint8_t *data, size_t length)
throw PortNotOpenedException ("Serial::write"); throw PortNotOpenedException ("Serial::write");
} }
DWORD bytes_written; DWORD bytes_written;
if (!WriteFile(fd_, data, length, &bytes_written, NULL)) { if (!WriteFile(fd_, data, static_cast<DWORD>(length), &bytes_written, NULL)) {
stringstream ss; stringstream ss;
ss << "Error while writing to the serial port: " << GetLastError(); ss << "Error while writing to the serial port: " << GetLastError();
THROW (IOException, ss.str().c_str()); THROW (IOException, ss.str().c_str());
@ -454,17 +471,23 @@ Serial::SerialImpl::flush ()
void void
Serial::SerialImpl::flushInput () Serial::SerialImpl::flushInput ()
{ {
THROW (IOException, "flushInput is not supported on Windows."); if (is_open_ == false) {
throw PortNotOpenedException("Serial::flushInput");
}
PurgeComm(fd_, PURGE_RXCLEAR);
} }
void void
Serial::SerialImpl::flushOutput () Serial::SerialImpl::flushOutput ()
{ {
THROW (IOException, "flushOutput is not supported on Windows."); if (is_open_ == false) {
throw PortNotOpenedException("Serial::flushOutput");
}
PurgeComm(fd_, PURGE_TXCLEAR);
} }
void void
Serial::SerialImpl::sendBreak (int duration) Serial::SerialImpl::sendBreak (int /*duration*/)
{ {
THROW (IOException, "sendBreak is not supported on Windows."); THROW (IOException, "sendBreak is not supported on Windows.");
} }

View File

@ -1,7 +1,7 @@
/* Copyright 2012 William Woodall and John Harrison */ /* Copyright 2012 William Woodall and John Harrison */
#include <algorithm> #include <algorithm>
#if !defined(_WIN32) && !defined(__OpenBSD__) #if !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__FreeBSD__)
# include <alloca.h> # include <alloca.h>
#endif #endif
@ -132,7 +132,16 @@ Serial::read (std::vector<uint8_t> &buffer, size_t size)
{ {
ScopedReadLock lock(this->pimpl_); ScopedReadLock lock(this->pimpl_);
uint8_t *buffer_ = new uint8_t[size]; uint8_t *buffer_ = new uint8_t[size];
size_t bytes_read = this->pimpl_->read (buffer_, size); size_t bytes_read = 0;
try {
bytes_read = this->pimpl_->read (buffer_, size);
}
catch (const std::exception &e) {
delete[] buffer_;
throw;
}
buffer.insert (buffer.end (), buffer_, buffer_+bytes_read); buffer.insert (buffer.end (), buffer_, buffer_+bytes_read);
delete[] buffer_; delete[] buffer_;
return bytes_read; return bytes_read;
@ -143,7 +152,14 @@ Serial::read (std::string &buffer, size_t size)
{ {
ScopedReadLock lock(this->pimpl_); ScopedReadLock lock(this->pimpl_);
uint8_t *buffer_ = new uint8_t[size]; uint8_t *buffer_ = new uint8_t[size];
size_t bytes_read = this->pimpl_->read (buffer_, size); size_t bytes_read = 0;
try {
bytes_read = this->pimpl_->read (buffer_, size);
}
catch (const std::exception &e) {
delete[] buffer_;
throw;
}
buffer.append (reinterpret_cast<const char*>(buffer_), bytes_read); buffer.append (reinterpret_cast<const char*>(buffer_), bytes_read);
delete[] buffer_; delete[] buffer_;
return bytes_read; return bytes_read;
@ -172,6 +188,7 @@ Serial::readline (string &buffer, size_t size, string eol)
if (bytes_read == 0) { if (bytes_read == 0) {
break; // Timeout occured on reading 1 byte break; // Timeout occured on reading 1 byte
} }
if(read_so_far < eol_len) continue;
if (string (reinterpret_cast<const char*> if (string (reinterpret_cast<const char*>
(buffer_ + read_so_far - eol_len), eol_len) == eol) { (buffer_ + read_so_far - eol_len), eol_len) == eol) {
break; // EOL found break; // EOL found
@ -213,6 +230,7 @@ Serial::readlines (size_t size, string eol)
} }
break; // Timeout occured on reading 1 byte break; // Timeout occured on reading 1 byte
} }
if(read_so_far < eol_len) continue;
if (string (reinterpret_cast<const char*> if (string (reinterpret_cast<const char*>
(buffer_ + read_so_far - eol_len), eol_len) == eol) { (buffer_ + read_so_far - eol_len), eol_len) == eol) {
// EOL found // EOL found

View File

@ -1,10 +1,12 @@
if(UNIX) if(UNIX)
catkin_add_gtest(${PROJECT_NAME}-test unix_serial_tests.cc) catkin_add_gtest(${PROJECT_NAME}-test unix_serial_tests.cc)
target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME} ${Boost_LIBRARIES}) target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
if(NOT APPLE) if(NOT APPLE)
target_link_libraries(${PROJECT_NAME}-test util) target_link_libraries(${PROJECT_NAME}-test util)
endif() endif()
catkin_add_gtest(${PROJECT_NAME}-test-timer unit/unix_timer_tests.cc) if(NOT APPLE) # these tests are unreliable on macOS
target_link_libraries(${PROJECT_NAME}-test-timer ${PROJECT_NAME}) catkin_add_gtest(${PROJECT_NAME}-test-timer unit/unix_timer_tests.cc)
target_link_libraries(${PROJECT_NAME}-test-timer ${PROJECT_NAME})
endif()
endif() endif()

View File

@ -20,8 +20,6 @@ void loop()
#include <string> #include <string>
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include <boost/bind.hpp>
// Use FRIEND_TEST... its not as nasty, thats what friends are for // Use FRIEND_TEST... its not as nasty, thats what friends are for
// // OMG this is so nasty... // // OMG this is so nasty...
// #define private public // #define private public

View File

@ -5,23 +5,47 @@
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32"> <ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}</ProjectGuid> <ProjectGuid>{A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}</ProjectGuid>
<RootNamespace>serial</RootNamespace> <RootNamespace>serial</RootNamespace>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<PlatformToolset Condition="'$(PlatformToolset)' == '' and '$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<PlatformToolset Condition="'$(PlatformToolset)' == '' and '$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(PlatformToolset)' == '' and '$(VisualStudioVersion)' == '11.0'">v110_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
@ -32,22 +56,43 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup /> <PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\serial\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
</Link> </Link>
<Lib> <Lib>
<AdditionalDependencies>setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Windows</SubSystem>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<AdditionalDependencies>setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Windows</SubSystem>
</Lib> </Lib>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -56,12 +101,35 @@
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
</Link> </Link>
<Lib>
<AdditionalDependencies>setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Windows</SubSystem>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<AdditionalDependencies>setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Windows</SubSystem>
</Lib>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\src\impl\list_ports\list_ports_win.cc" /> <ClCompile Include="..\..\src\impl\list_ports\list_ports_win.cc" />

View File

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>

View File

@ -5,46 +5,88 @@
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32"> <ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}</ProjectGuid> <ProjectGuid>{92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}</ProjectGuid>
<RootNamespace>test_serial</RootNamespace> <RootNamespace>test_serial</RootNamespace>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<PlatformToolset Condition="'$(PlatformToolset)' == '' and '$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<PlatformToolset Condition="'$(PlatformToolset)' == '' and '$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(PlatformToolset)' == '' and '$(VisualStudioVersion)' == '11.0'">v110_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup /> <PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\serial\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir)..\..\include</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -53,11 +95,28 @@
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\include</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<SubSystem>Console</SubSystem>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>

View File

@ -8,17 +8,27 @@ EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32 Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}.Debug|Win32.ActiveCfg = Debug|Win32 {A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}.Debug|Win32.ActiveCfg = Debug|Win32
{A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}.Debug|Win32.Build.0 = Debug|Win32 {A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}.Debug|Win32.Build.0 = Debug|Win32
{A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}.Debug|x64.ActiveCfg = Debug|x64
{A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}.Debug|x64.Build.0 = Debug|x64
{A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}.Release|Win32.ActiveCfg = Release|Win32 {A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}.Release|Win32.ActiveCfg = Release|Win32
{A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}.Release|Win32.Build.0 = Release|Win32 {A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}.Release|Win32.Build.0 = Release|Win32
{A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}.Release|x64.ActiveCfg = Release|x64
{A8517FB2-C74E-43BD-B3C6-B05D3FC11ECD}.Release|x64.Build.0 = Release|x64
{92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}.Debug|Win32.ActiveCfg = Debug|Win32 {92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}.Debug|Win32.ActiveCfg = Debug|Win32
{92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}.Debug|Win32.Build.0 = Debug|Win32 {92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}.Debug|Win32.Build.0 = Debug|Win32
{92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}.Debug|x64.ActiveCfg = Debug|x64
{92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}.Debug|x64.Build.0 = Debug|x64
{92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}.Release|Win32.ActiveCfg = Release|Win32 {92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}.Release|Win32.ActiveCfg = Release|Win32
{92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}.Release|Win32.Build.0 = Release|Win32 {92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}.Release|Win32.Build.0 = Release|Win32
{92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}.Release|x64.ActiveCfg = Release|x64
{92EE7E58-C737-41F9-B795-9B6ACF6AB0B8}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE