OSVR Framework (Internal Development Docs)  0.6-1962-g59773924
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
GetSerialPortState.cpp
Go to the documentation of this file.
1 
11 // Copyright 2015 Sensics, Inc.
12 //
13 // Licensed under the Apache License, Version 2.0 (the "License");
14 // you may not use this file except in compliance with the License.
15 // You may obtain a copy of the License at
16 //
17 // http://www.apache.org/licenses/LICENSE-2.0
18 //
19 // Unless required by applicable law or agreed to in writing, software
20 // distributed under the License is distributed on an "AS IS" BASIS,
21 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 // See the License for the specific language governing permissions and
23 // limitations under the License.
24 
25 // Internal Includes
26 #include "GetSerialPortState.h"
27 #include <osvr/Util/MacroToolsC.h>
28 #include <osvr/Util/Finally.h>
29 
30 // Library/third-party includes
31 // - none
32 
33 // Standard includes
34 #include <stdexcept>
35 
36 #if defined(_WIN32)
37 #define WIN32_LEAN_AND_MEAN
38 #include <windows.h>
39 
40 // Inspired by answer by Yangghi Min on
41 // https://social.msdn.microsoft.com/Forums/vstudio/en-US/588b7967-cce4-4412-87e8-593dfeb228b4/getting-the-list-of-available-serial-ports-in-c
42 inline SerialPortState getSerialPortStateImpl(std::string const &port) {
43  GetLastError(); // clear last error
44  HANDLE hCom = CreateFile(port.c_str(), GENERIC_READ | GENERIC_WRITE,
45  0, // non-sharing mode
46  nullptr, // ignore security
47  OPEN_EXISTING, // required for com ports
48  0, // just basic open for existence test.
49  nullptr);
50 
52  auto f = osvr::util::finally([&hCom] { CloseHandle(hCom); });
53 
54  if (INVALID_HANDLE_VALUE == hCom) {
55  auto err = GetLastError();
56  if (ERROR_ACCESS_DENIED == err) {
57  return SERIAL_BUSY;
58  }
59  return SERIAL_MISSING;
60  }
61  return SERIAL_AVAILABLE;
62 }
63 #else
64 
65 inline SerialPortState getSerialPortStateImpl(std::string const &port) {
68  return SERIAL_AVAILABLE;
69 }
70 #endif
71 
72 SerialPortState getSerialPortState(std::string const &port) {
73  if (port.empty()) {
74  return SERIAL_MISSING;
75  }
76  return getSerialPortStateImpl(port);
77 }
78 
79 std::string normalizeSerialPort(std::string const &port) {
80  if (port.empty()) {
81  return port;
82  }
83 #ifdef _WIN32
84  // Use the Win32 device namespace, if they aren't already.
85  // Have to double the backslashes because they're escape characters.
87  if (port.find('\\') == std::string::npos) {
88  return "\\\\.\\" + port;
89  }
90 #endif
91  return port;
92 }
93 
94 void verifySerialPort(std::string const &port, std::string const &origPort) {
95  std::string const *origPortPtr = origPort.empty() ? &port : &origPort;
96  auto portState = getSerialPortState(port);
97  if (SERIAL_BUSY == portState) {
98  throw std::runtime_error("Cannot access " + *origPortPtr +
99  ": currently busy. Do you have another "
100  "application open using that port?");
101  } else if (SERIAL_MISSING == portState) {
102  throw std::runtime_error("Cannot access " + *origPortPtr +
103  ": port apparently not found. Make sure the "
104  "device is plugged in and you've specified "
105  "the right device and the right port.");
106  } else if (SERIAL_INVALID == portState) {
107  throw std::runtime_error("Cannot access serial port '" + *origPortPtr +
108  "': apparently invalid.");
109  } else if (SERIAL_AVAILABLE != portState) {
111  throw std::runtime_error("Cannot access serial port '" + *origPortPtr +
112  "'");
113  }
114 }
115 
116 std::string normalizeAndVerifySerialPort(std::string const &port) {
117  std::string ret = normalizeSerialPort(port);
118  verifySerialPort(ret, port);
119 
120  return ret;
121 }
SerialPortState
Header declaring a C++11 finally or "scope-guard" construct.
std::string normalizeSerialPort(std::string const &port)
Normalizes the name of a serial port.
SerialPortState getSerialPortState(std::string const &port)
Returns an enum value indicating the apparent state of the port.
void verifySerialPort(std::string const &port, std::string const &origPort)
Verifies the accessibility of a serial port and throws a std::exception unless it is available...
Something's wrong with the port name you gave.
FinalTask< F > finally(F &&f)
Definition: Finally.h:87
serial port requested is missing.
Header containing basic macro tools.
std::string normalizeAndVerifySerialPort(std::string const &port)
Normalizes and verifies the accessibility of a serial port and throws a std::exception unless it is a...
SerialPortState getSerialPortStateImpl(std::string const &port)