add --serial option in premake, added serial library to test vr glove in C++ (pybullet works already fine)
This commit is contained in:
@@ -0,0 +1,335 @@
|
||||
#if defined(__linux__)
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Craig Lilley <cralilley@gmail.com>
|
||||
* This software is made available under the terms of the MIT licence.
|
||||
* A copy of the licence can be obtained from:
|
||||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <glob.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "serial/serial.h"
|
||||
|
||||
using serial::PortInfo;
|
||||
using std::istringstream;
|
||||
using std::ifstream;
|
||||
using std::getline;
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
static vector<string> glob(const vector<string>& patterns);
|
||||
static string basename(const string& path);
|
||||
static string dirname(const string& path);
|
||||
static bool path_exists(const string& path);
|
||||
static string realpath(const string& path);
|
||||
static string usb_sysfs_friendly_name(const string& sys_usb_path);
|
||||
static vector<string> get_sysfs_info(const string& device_path);
|
||||
static string read_line(const string& file);
|
||||
static string usb_sysfs_hw_string(const string& sysfs_path);
|
||||
static string format(const char* format, ...);
|
||||
|
||||
vector<string>
|
||||
glob(const vector<string>& patterns)
|
||||
{
|
||||
vector<string> paths_found;
|
||||
|
||||
if(patterns.size() == 0)
|
||||
return paths_found;
|
||||
|
||||
glob_t glob_results;
|
||||
|
||||
int glob_retval = glob(patterns[0].c_str(), 0, NULL, &glob_results);
|
||||
|
||||
vector<string>::const_iterator iter = patterns.begin();
|
||||
|
||||
while(++iter != patterns.end())
|
||||
{
|
||||
glob_retval = glob(iter->c_str(), GLOB_APPEND, NULL, &glob_results);
|
||||
}
|
||||
|
||||
for(int path_index = 0; path_index < glob_results.gl_pathc; path_index++)
|
||||
{
|
||||
paths_found.push_back(glob_results.gl_pathv[path_index]);
|
||||
}
|
||||
|
||||
globfree(&glob_results);
|
||||
|
||||
return paths_found;
|
||||
}
|
||||
|
||||
string
|
||||
basename(const string& path)
|
||||
{
|
||||
size_t pos = path.rfind("/");
|
||||
|
||||
if(pos == std::string::npos)
|
||||
return path;
|
||||
|
||||
return string(path, pos+1, string::npos);
|
||||
}
|
||||
|
||||
string
|
||||
dirname(const string& path)
|
||||
{
|
||||
size_t pos = path.rfind("/");
|
||||
|
||||
if(pos == std::string::npos)
|
||||
return path;
|
||||
else if(pos == 0)
|
||||
return "/";
|
||||
|
||||
return string(path, 0, pos);
|
||||
}
|
||||
|
||||
bool
|
||||
path_exists(const string& path)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if( stat(path.c_str(), &sb ) == 0 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string
|
||||
realpath(const string& path)
|
||||
{
|
||||
char* real_path = realpath(path.c_str(), NULL);
|
||||
|
||||
string result;
|
||||
|
||||
if(real_path != NULL)
|
||||
{
|
||||
result = real_path;
|
||||
|
||||
free(real_path);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
string
|
||||
usb_sysfs_friendly_name(const string& sys_usb_path)
|
||||
{
|
||||
unsigned int device_number = 0;
|
||||
|
||||
istringstream( read_line(sys_usb_path + "/devnum") ) >> device_number;
|
||||
|
||||
string manufacturer = read_line( sys_usb_path + "/manufacturer" );
|
||||
|
||||
string product = read_line( sys_usb_path + "/product" );
|
||||
|
||||
string serial = read_line( sys_usb_path + "/serial" );
|
||||
|
||||
if( manufacturer.empty() && product.empty() && serial.empty() )
|
||||
return "";
|
||||
|
||||
return format("%s %s %s", manufacturer.c_str(), product.c_str(), serial.c_str() );
|
||||
}
|
||||
|
||||
vector<string>
|
||||
get_sysfs_info(const string& device_path)
|
||||
{
|
||||
string device_name = basename( device_path );
|
||||
|
||||
string friendly_name;
|
||||
|
||||
string hardware_id;
|
||||
|
||||
string sys_device_path = format( "/sys/class/tty/%s/device", device_name.c_str() );
|
||||
|
||||
if( device_name.compare(0,6,"ttyUSB") == 0 )
|
||||
{
|
||||
sys_device_path = dirname( dirname( realpath( sys_device_path ) ) );
|
||||
|
||||
if( path_exists( sys_device_path ) )
|
||||
{
|
||||
friendly_name = usb_sysfs_friendly_name( sys_device_path );
|
||||
|
||||
hardware_id = usb_sysfs_hw_string( sys_device_path );
|
||||
}
|
||||
}
|
||||
else if( device_name.compare(0,6,"ttyACM") == 0 )
|
||||
{
|
||||
sys_device_path = dirname( realpath( sys_device_path ) );
|
||||
|
||||
if( path_exists( sys_device_path ) )
|
||||
{
|
||||
friendly_name = usb_sysfs_friendly_name( sys_device_path );
|
||||
|
||||
hardware_id = usb_sysfs_hw_string( sys_device_path );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to read ID string of PCI device
|
||||
|
||||
string sys_id_path = sys_device_path + "/id";
|
||||
|
||||
if( path_exists( sys_id_path ) )
|
||||
hardware_id = read_line( sys_id_path );
|
||||
}
|
||||
|
||||
if( friendly_name.empty() )
|
||||
friendly_name = device_name;
|
||||
|
||||
if( hardware_id.empty() )
|
||||
hardware_id = "n/a";
|
||||
|
||||
vector<string> result;
|
||||
result.push_back(friendly_name);
|
||||
result.push_back(hardware_id);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
string
|
||||
read_line(const string& file)
|
||||
{
|
||||
ifstream ifs(file.c_str(), ifstream::in);
|
||||
|
||||
string line;
|
||||
|
||||
if(ifs)
|
||||
{
|
||||
getline(ifs, line);
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
string
|
||||
format(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
size_t buffer_size_bytes = 256;
|
||||
|
||||
string result;
|
||||
|
||||
char* buffer = (char*)malloc(buffer_size_bytes);
|
||||
|
||||
if( buffer == NULL )
|
||||
return result;
|
||||
|
||||
bool done = false;
|
||||
|
||||
unsigned int loop_count = 0;
|
||||
|
||||
while(!done)
|
||||
{
|
||||
va_start(ap, format);
|
||||
|
||||
int return_value = vsnprintf(buffer, buffer_size_bytes, format, ap);
|
||||
|
||||
if( return_value < 0 )
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
else if( return_value >= buffer_size_bytes )
|
||||
{
|
||||
// Realloc and try again.
|
||||
|
||||
buffer_size_bytes = return_value + 1;
|
||||
|
||||
char* new_buffer_ptr = (char*)realloc(buffer, buffer_size_bytes);
|
||||
|
||||
if( new_buffer_ptr == NULL )
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = new_buffer_ptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = buffer;
|
||||
done = true;
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
if( ++loop_count > 5 )
|
||||
done = true;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
string
|
||||
usb_sysfs_hw_string(const string& sysfs_path)
|
||||
{
|
||||
string serial_number = read_line( sysfs_path + "/serial" );
|
||||
|
||||
if( serial_number.length() > 0 )
|
||||
{
|
||||
serial_number = format( "SNR=%s", serial_number.c_str() );
|
||||
}
|
||||
|
||||
string vid = read_line( sysfs_path + "/idVendor" );
|
||||
|
||||
string pid = read_line( sysfs_path + "/idProduct" );
|
||||
|
||||
return format("USB VID:PID=%s:%s %s", vid.c_str(), pid.c_str(), serial_number.c_str() );
|
||||
}
|
||||
|
||||
vector<PortInfo>
|
||||
serial::list_ports()
|
||||
{
|
||||
vector<PortInfo> results;
|
||||
|
||||
vector<string> search_globs;
|
||||
search_globs.push_back("/dev/ttyACM*");
|
||||
search_globs.push_back("/dev/ttyS*");
|
||||
search_globs.push_back("/dev/ttyUSB*");
|
||||
search_globs.push_back("/dev/tty.*");
|
||||
search_globs.push_back("/dev/cu.*");
|
||||
|
||||
vector<string> devices_found = glob( search_globs );
|
||||
|
||||
vector<string>::iterator iter = devices_found.begin();
|
||||
|
||||
while( iter != devices_found.end() )
|
||||
{
|
||||
string device = *iter++;
|
||||
|
||||
vector<string> sysfs_info = get_sysfs_info( device );
|
||||
|
||||
string friendly_name = sysfs_info[0];
|
||||
|
||||
string hardware_id = sysfs_info[1];
|
||||
|
||||
PortInfo device_entry;
|
||||
device_entry.port = device;
|
||||
device_entry.description = friendly_name;
|
||||
device_entry.hardware_id = hardware_id;
|
||||
|
||||
results.push_back( device_entry );
|
||||
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
#endif // defined(__linux__)
|
||||
@@ -0,0 +1,286 @@
|
||||
#if defined(__APPLE__)
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/serial/IOSerialKeys.h>
|
||||
#include <IOKit/IOBSD.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "serial/serial.h"
|
||||
|
||||
using serial::PortInfo;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
#define HARDWARE_ID_STRING_LENGTH 128
|
||||
|
||||
string cfstring_to_string( CFStringRef cfstring );
|
||||
string get_device_path( io_object_t& serial_port );
|
||||
string get_class_name( io_object_t& obj );
|
||||
io_registry_entry_t get_parent_iousb_device( io_object_t& serial_port );
|
||||
string get_string_property( io_object_t& device, const char* property );
|
||||
uint16_t get_int_property( io_object_t& device, const char* property );
|
||||
string rtrim(const string& str);
|
||||
|
||||
string
|
||||
cfstring_to_string( CFStringRef cfstring )
|
||||
{
|
||||
char cstring[MAXPATHLEN];
|
||||
string result;
|
||||
|
||||
if( cfstring )
|
||||
{
|
||||
Boolean success = CFStringGetCString( cfstring,
|
||||
cstring,
|
||||
sizeof(cstring),
|
||||
kCFStringEncodingASCII );
|
||||
|
||||
if( success )
|
||||
result = cstring;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
string
|
||||
get_device_path( io_object_t& serial_port )
|
||||
{
|
||||
CFTypeRef callout_path;
|
||||
string device_path;
|
||||
|
||||
callout_path = IORegistryEntryCreateCFProperty( serial_port,
|
||||
CFSTR(kIOCalloutDeviceKey),
|
||||
kCFAllocatorDefault,
|
||||
0 );
|
||||
|
||||
if (callout_path)
|
||||
{
|
||||
if( CFGetTypeID(callout_path) == CFStringGetTypeID() )
|
||||
device_path = cfstring_to_string( static_cast<CFStringRef>(callout_path) );
|
||||
|
||||
CFRelease(callout_path);
|
||||
}
|
||||
|
||||
return device_path;
|
||||
}
|
||||
|
||||
string
|
||||
get_class_name( io_object_t& obj )
|
||||
{
|
||||
string result;
|
||||
io_name_t class_name;
|
||||
kern_return_t kern_result;
|
||||
|
||||
kern_result = IOObjectGetClass( obj, class_name );
|
||||
|
||||
if( kern_result == KERN_SUCCESS )
|
||||
result = class_name;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
io_registry_entry_t
|
||||
get_parent_iousb_device( io_object_t& serial_port )
|
||||
{
|
||||
io_object_t device = serial_port;
|
||||
io_registry_entry_t parent = 0;
|
||||
io_registry_entry_t result = 0;
|
||||
kern_return_t kern_result = KERN_FAILURE;
|
||||
string name = get_class_name(device);
|
||||
|
||||
// Walk the IO Registry tree looking for this devices parent IOUSBDevice.
|
||||
while( name != "IOUSBDevice" )
|
||||
{
|
||||
kern_result = IORegistryEntryGetParentEntry( device,
|
||||
kIOServicePlane,
|
||||
&parent );
|
||||
|
||||
if(kern_result != KERN_SUCCESS)
|
||||
{
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
device = parent;
|
||||
|
||||
name = get_class_name(device);
|
||||
}
|
||||
|
||||
if(kern_result == KERN_SUCCESS)
|
||||
result = device;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
string
|
||||
get_string_property( io_object_t& device, const char* property )
|
||||
{
|
||||
string property_name;
|
||||
|
||||
if( device )
|
||||
{
|
||||
CFStringRef property_as_cfstring = CFStringCreateWithCString (
|
||||
kCFAllocatorDefault,
|
||||
property,
|
||||
kCFStringEncodingASCII );
|
||||
|
||||
CFTypeRef name_as_cfstring = IORegistryEntryCreateCFProperty(
|
||||
device,
|
||||
property_as_cfstring,
|
||||
kCFAllocatorDefault,
|
||||
0 );
|
||||
|
||||
if( name_as_cfstring )
|
||||
{
|
||||
if( CFGetTypeID(name_as_cfstring) == CFStringGetTypeID() )
|
||||
property_name = cfstring_to_string( static_cast<CFStringRef>(name_as_cfstring) );
|
||||
|
||||
CFRelease(name_as_cfstring);
|
||||
}
|
||||
|
||||
if(property_as_cfstring)
|
||||
CFRelease(property_as_cfstring);
|
||||
}
|
||||
|
||||
return property_name;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
get_int_property( io_object_t& device, const char* property )
|
||||
{
|
||||
uint16_t result = 0;
|
||||
|
||||
if( device )
|
||||
{
|
||||
CFStringRef property_as_cfstring = CFStringCreateWithCString (
|
||||
kCFAllocatorDefault,
|
||||
property,
|
||||
kCFStringEncodingASCII );
|
||||
|
||||
CFTypeRef number = IORegistryEntryCreateCFProperty( device,
|
||||
property_as_cfstring,
|
||||
kCFAllocatorDefault,
|
||||
0 );
|
||||
|
||||
if(property_as_cfstring)
|
||||
CFRelease(property_as_cfstring);
|
||||
|
||||
if( number )
|
||||
{
|
||||
if( CFGetTypeID(number) == CFNumberGetTypeID() )
|
||||
{
|
||||
bool success = CFNumberGetValue( static_cast<CFNumberRef>(number),
|
||||
kCFNumberSInt16Type,
|
||||
&result );
|
||||
|
||||
if( !success )
|
||||
result = 0;
|
||||
}
|
||||
|
||||
CFRelease(number);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
string rtrim(const string& str)
|
||||
{
|
||||
string result = str;
|
||||
|
||||
string whitespace = " \t\f\v\n\r";
|
||||
|
||||
std::size_t found = result.find_last_not_of(whitespace);
|
||||
|
||||
if (found != std::string::npos)
|
||||
result.erase(found+1);
|
||||
else
|
||||
result.clear();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<PortInfo>
|
||||
serial::list_ports(void)
|
||||
{
|
||||
vector<PortInfo> devices_found;
|
||||
CFMutableDictionaryRef classes_to_match;
|
||||
io_iterator_t serial_port_iterator;
|
||||
io_object_t serial_port;
|
||||
mach_port_t master_port;
|
||||
kern_return_t kern_result;
|
||||
|
||||
kern_result = IOMasterPort(MACH_PORT_NULL, &master_port);
|
||||
|
||||
if(kern_result != KERN_SUCCESS)
|
||||
return devices_found;
|
||||
|
||||
classes_to_match = IOServiceMatching(kIOSerialBSDServiceValue);
|
||||
|
||||
if (classes_to_match == NULL)
|
||||
return devices_found;
|
||||
|
||||
CFDictionarySetValue( classes_to_match,
|
||||
CFSTR(kIOSerialBSDTypeKey),
|
||||
CFSTR(kIOSerialBSDAllTypes) );
|
||||
|
||||
kern_result = IOServiceGetMatchingServices(master_port, classes_to_match, &serial_port_iterator);
|
||||
|
||||
if (KERN_SUCCESS != kern_result)
|
||||
return devices_found;
|
||||
|
||||
while ( (serial_port = IOIteratorNext(serial_port_iterator)) )
|
||||
{
|
||||
string device_path = get_device_path( serial_port );
|
||||
io_registry_entry_t parent = get_parent_iousb_device( serial_port );
|
||||
IOObjectRelease(serial_port);
|
||||
|
||||
if( device_path.empty() )
|
||||
continue;
|
||||
|
||||
PortInfo port_info;
|
||||
port_info.port = device_path;
|
||||
port_info.description = "n/a";
|
||||
port_info.hardware_id = "n/a";
|
||||
|
||||
string device_name = rtrim( get_string_property( parent, "USB Product Name" ) );
|
||||
string vendor_name = rtrim( get_string_property( parent, "USB Vendor Name") );
|
||||
string description = rtrim( vendor_name + " " + device_name );
|
||||
if( !description.empty() )
|
||||
port_info.description = description;
|
||||
|
||||
string serial_number = rtrim(get_string_property( parent, "USB Serial Number" ) );
|
||||
uint16_t vendor_id = get_int_property( parent, "idVendor" );
|
||||
uint16_t product_id = get_int_property( parent, "idProduct" );
|
||||
|
||||
if( vendor_id && product_id )
|
||||
{
|
||||
char cstring[HARDWARE_ID_STRING_LENGTH];
|
||||
|
||||
if(serial_number.empty())
|
||||
serial_number = "None";
|
||||
|
||||
int ret = snprintf( cstring, HARDWARE_ID_STRING_LENGTH, "USB VID:PID=%04x:%04x SNR=%s",
|
||||
vendor_id,
|
||||
product_id,
|
||||
serial_number.c_str() );
|
||||
|
||||
if( (ret >= 0) && (ret < HARDWARE_ID_STRING_LENGTH) )
|
||||
port_info.hardware_id = cstring;
|
||||
}
|
||||
|
||||
devices_found.push_back(port_info);
|
||||
}
|
||||
|
||||
IOObjectRelease(serial_port_iterator);
|
||||
return devices_found;
|
||||
}
|
||||
|
||||
#endif // defined(__APPLE__)
|
||||
@@ -0,0 +1,152 @@
|
||||
#if defined(_WIN32)
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Craig Lilley <cralilley@gmail.com>
|
||||
* This software is made available under the terms of the MIT licence.
|
||||
* A copy of the licence can be obtained from:
|
||||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "serial/serial.h"
|
||||
#include <tchar.h>
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <initguid.h>
|
||||
#include <devguid.h>
|
||||
#include <cstring>
|
||||
|
||||
using serial::PortInfo;
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
static const DWORD port_name_max_length = 256;
|
||||
static const DWORD friendly_name_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>
|
||||
serial::list_ports()
|
||||
{
|
||||
vector<PortInfo> devices_found;
|
||||
|
||||
HDEVINFO device_info_set = SetupDiGetClassDevs(
|
||||
(const GUID *) &GUID_DEVCLASS_PORTS,
|
||||
NULL,
|
||||
NULL,
|
||||
DIGCF_PRESENT);
|
||||
|
||||
unsigned int device_info_set_index = 0;
|
||||
SP_DEVINFO_DATA device_info_data;
|
||||
|
||||
device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
|
||||
while(SetupDiEnumDeviceInfo(device_info_set, device_info_set_index, &device_info_data))
|
||||
{
|
||||
device_info_set_index++;
|
||||
|
||||
// Get port name
|
||||
|
||||
HKEY hkey = SetupDiOpenDevRegKey(
|
||||
device_info_set,
|
||||
&device_info_data,
|
||||
DICS_FLAG_GLOBAL,
|
||||
0,
|
||||
DIREG_DEV,
|
||||
KEY_READ);
|
||||
|
||||
TCHAR port_name[port_name_max_length];
|
||||
DWORD port_name_length = port_name_max_length;
|
||||
|
||||
LONG return_code = RegQueryValueEx(
|
||||
hkey,
|
||||
_T("PortName"),
|
||||
NULL,
|
||||
NULL,
|
||||
(LPBYTE)port_name,
|
||||
&port_name_length);
|
||||
|
||||
RegCloseKey(hkey);
|
||||
|
||||
if(return_code != EXIT_SUCCESS)
|
||||
continue;
|
||||
|
||||
if(port_name_length > 0 && port_name_length <= port_name_max_length)
|
||||
port_name[port_name_length-1] = '\0';
|
||||
else
|
||||
port_name[0] = '\0';
|
||||
|
||||
// Ignore parallel ports
|
||||
|
||||
if(_tcsstr(port_name, _T("LPT")) != NULL)
|
||||
continue;
|
||||
|
||||
// Get port friendly name
|
||||
|
||||
TCHAR friendly_name[friendly_name_max_length];
|
||||
DWORD friendly_name_actual_length = 0;
|
||||
|
||||
BOOL got_friendly_name = SetupDiGetDeviceRegistryProperty(
|
||||
device_info_set,
|
||||
&device_info_data,
|
||||
SPDRP_FRIENDLYNAME,
|
||||
NULL,
|
||||
(PBYTE)friendly_name,
|
||||
friendly_name_max_length,
|
||||
&friendly_name_actual_length);
|
||||
|
||||
if(got_friendly_name == TRUE && friendly_name_actual_length > 0)
|
||||
friendly_name[friendly_name_actual_length-1] = '\0';
|
||||
else
|
||||
friendly_name[0] = '\0';
|
||||
|
||||
// Get hardware ID
|
||||
|
||||
TCHAR hardware_id[hardware_id_max_length];
|
||||
DWORD hardware_id_actual_length = 0;
|
||||
|
||||
BOOL got_hardware_id = SetupDiGetDeviceRegistryProperty(
|
||||
device_info_set,
|
||||
&device_info_data,
|
||||
SPDRP_HARDWAREID,
|
||||
NULL,
|
||||
(PBYTE)hardware_id,
|
||||
hardware_id_max_length,
|
||||
&hardware_id_actual_length);
|
||||
|
||||
if(got_hardware_id == TRUE && hardware_id_actual_length > 0)
|
||||
hardware_id[hardware_id_actual_length-1] = '\0';
|
||||
else
|
||||
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;
|
||||
port_entry.port = portName;
|
||||
port_entry.description = friendlyName;
|
||||
port_entry.hardware_id = hardwareId;
|
||||
|
||||
devices_found.push_back(port_entry);
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(device_info_set);
|
||||
|
||||
return devices_found;
|
||||
}
|
||||
|
||||
#endif // #if defined(_WIN32)
|
||||
1063
examples/ThirdPartyLibs/serial/src/impl/unix.cc
Normal file
1063
examples/ThirdPartyLibs/serial/src/impl/unix.cc
Normal file
File diff suppressed because it is too large
Load Diff
640
examples/ThirdPartyLibs/serial/src/impl/win.cc
Normal file
640
examples/ThirdPartyLibs/serial/src/impl/win.cc
Normal file
@@ -0,0 +1,640 @@
|
||||
#if defined(_WIN32)
|
||||
|
||||
/* Copyright 2012 William Woodall and John Harrison */
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "serial/impl/win.h"
|
||||
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using std::stringstream;
|
||||
using std::invalid_argument;
|
||||
using serial::Serial;
|
||||
using serial::Timeout;
|
||||
using serial::bytesize_t;
|
||||
using serial::parity_t;
|
||||
using serial::stopbits_t;
|
||||
using serial::flowcontrol_t;
|
||||
using serial::SerialException;
|
||||
using serial::PortNotOpenedException;
|
||||
using serial::IOException;
|
||||
|
||||
inline wstring
|
||||
_prefix_port_if_needed(const wstring &input)
|
||||
{
|
||||
static wstring windows_com_port_prefix = L"\\\\.\\";
|
||||
if (input.compare(windows_com_port_prefix) != 0)
|
||||
{
|
||||
return windows_com_port_prefix + input;
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
|
||||
bytesize_t bytesize,
|
||||
parity_t parity, stopbits_t stopbits,
|
||||
flowcontrol_t flowcontrol)
|
||||
: port_ (port.begin(), port.end()), fd_ (INVALID_HANDLE_VALUE), is_open_ (false),
|
||||
baudrate_ (baudrate), parity_ (parity),
|
||||
bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol)
|
||||
{
|
||||
if (port_.empty () == false)
|
||||
open ();
|
||||
read_mutex = CreateMutex(NULL, false, NULL);
|
||||
write_mutex = CreateMutex(NULL, false, NULL);
|
||||
}
|
||||
|
||||
Serial::SerialImpl::~SerialImpl ()
|
||||
{
|
||||
this->close();
|
||||
CloseHandle(read_mutex);
|
||||
CloseHandle(write_mutex);
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::open ()
|
||||
{
|
||||
if (port_.empty ()) {
|
||||
throw invalid_argument ("Empty port is invalid.");
|
||||
}
|
||||
if (is_open_ == true) {
|
||||
throw SerialException ("Serial port already open.");
|
||||
}
|
||||
|
||||
// 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,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0);
|
||||
|
||||
if (fd_ == INVALID_HANDLE_VALUE) {
|
||||
DWORD errno_ = GetLastError();
|
||||
stringstream ss;
|
||||
switch (errno_) {
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
// Use this->getPort to convert to a std::string
|
||||
ss << "Specified port, " << this->getPort() << ", does not exist.";
|
||||
THROW (IOException, ss.str().c_str());
|
||||
default:
|
||||
ss << "Unknown error opening the serial port: " << errno;
|
||||
THROW (IOException, ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
reconfigurePort();
|
||||
is_open_ = true;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::reconfigurePort ()
|
||||
{
|
||||
if (fd_ == INVALID_HANDLE_VALUE) {
|
||||
// Can only operate on a valid file descriptor
|
||||
THROW (IOException, "Invalid file descriptor, is the serial port open?");
|
||||
}
|
||||
|
||||
DCB dcbSerialParams = {0};
|
||||
|
||||
dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
|
||||
|
||||
if (!GetCommState(fd_, &dcbSerialParams)) {
|
||||
//error getting state
|
||||
THROW (IOException, "Error getting the serial port state.");
|
||||
}
|
||||
|
||||
// setup baud rate
|
||||
switch (baudrate_) {
|
||||
#ifdef CBR_0
|
||||
case 0: dcbSerialParams.BaudRate = CBR_0; break;
|
||||
#endif
|
||||
#ifdef CBR_50
|
||||
case 50: dcbSerialParams.BaudRate = CBR_50; break;
|
||||
#endif
|
||||
#ifdef CBR_75
|
||||
case 75: dcbSerialParams.BaudRate = CBR_75; break;
|
||||
#endif
|
||||
#ifdef CBR_110
|
||||
case 110: dcbSerialParams.BaudRate = CBR_110; break;
|
||||
#endif
|
||||
#ifdef CBR_134
|
||||
case 134: dcbSerialParams.BaudRate = CBR_134; break;
|
||||
#endif
|
||||
#ifdef CBR_150
|
||||
case 150: dcbSerialParams.BaudRate = CBR_150; break;
|
||||
#endif
|
||||
#ifdef CBR_200
|
||||
case 200: dcbSerialParams.BaudRate = CBR_200; break;
|
||||
#endif
|
||||
#ifdef CBR_300
|
||||
case 300: dcbSerialParams.BaudRate = CBR_300; break;
|
||||
#endif
|
||||
#ifdef CBR_600
|
||||
case 600: dcbSerialParams.BaudRate = CBR_600; break;
|
||||
#endif
|
||||
#ifdef CBR_1200
|
||||
case 1200: dcbSerialParams.BaudRate = CBR_1200; break;
|
||||
#endif
|
||||
#ifdef CBR_1800
|
||||
case 1800: dcbSerialParams.BaudRate = CBR_1800; break;
|
||||
#endif
|
||||
#ifdef CBR_2400
|
||||
case 2400: dcbSerialParams.BaudRate = CBR_2400; break;
|
||||
#endif
|
||||
#ifdef CBR_4800
|
||||
case 4800: dcbSerialParams.BaudRate = CBR_4800; break;
|
||||
#endif
|
||||
#ifdef CBR_7200
|
||||
case 7200: dcbSerialParams.BaudRate = CBR_7200; break;
|
||||
#endif
|
||||
#ifdef CBR_9600
|
||||
case 9600: dcbSerialParams.BaudRate = CBR_9600; break;
|
||||
#endif
|
||||
#ifdef CBR_14400
|
||||
case 14400: dcbSerialParams.BaudRate = CBR_14400; break;
|
||||
#endif
|
||||
#ifdef CBR_19200
|
||||
case 19200: dcbSerialParams.BaudRate = CBR_19200; break;
|
||||
#endif
|
||||
#ifdef CBR_28800
|
||||
case 28800: dcbSerialParams.BaudRate = CBR_28800; break;
|
||||
#endif
|
||||
#ifdef CBR_57600
|
||||
case 57600: dcbSerialParams.BaudRate = CBR_57600; break;
|
||||
#endif
|
||||
#ifdef CBR_76800
|
||||
case 76800: dcbSerialParams.BaudRate = CBR_76800; break;
|
||||
#endif
|
||||
#ifdef CBR_38400
|
||||
case 38400: dcbSerialParams.BaudRate = CBR_38400; break;
|
||||
#endif
|
||||
#ifdef CBR_115200
|
||||
case 115200: dcbSerialParams.BaudRate = CBR_115200; break;
|
||||
#endif
|
||||
#ifdef CBR_128000
|
||||
case 128000: dcbSerialParams.BaudRate = CBR_128000; break;
|
||||
#endif
|
||||
#ifdef CBR_153600
|
||||
case 153600: dcbSerialParams.BaudRate = CBR_153600; break;
|
||||
#endif
|
||||
#ifdef CBR_230400
|
||||
case 230400: dcbSerialParams.BaudRate = CBR_230400; break;
|
||||
#endif
|
||||
#ifdef CBR_256000
|
||||
case 256000: dcbSerialParams.BaudRate = CBR_256000; break;
|
||||
#endif
|
||||
#ifdef CBR_460800
|
||||
case 460800: dcbSerialParams.BaudRate = CBR_460800; break;
|
||||
#endif
|
||||
#ifdef CBR_921600
|
||||
case 921600: dcbSerialParams.BaudRate = CBR_921600; break;
|
||||
#endif
|
||||
default:
|
||||
// Try to blindly assign it
|
||||
dcbSerialParams.BaudRate = baudrate_;
|
||||
}
|
||||
|
||||
// setup char len
|
||||
if (bytesize_ == eightbits)
|
||||
dcbSerialParams.ByteSize = 8;
|
||||
else if (bytesize_ == sevenbits)
|
||||
dcbSerialParams.ByteSize = 7;
|
||||
else if (bytesize_ == sixbits)
|
||||
dcbSerialParams.ByteSize = 6;
|
||||
else if (bytesize_ == fivebits)
|
||||
dcbSerialParams.ByteSize = 5;
|
||||
else
|
||||
throw invalid_argument ("invalid char len");
|
||||
|
||||
// setup stopbits
|
||||
if (stopbits_ == stopbits_one)
|
||||
dcbSerialParams.StopBits = ONESTOPBIT;
|
||||
else if (stopbits_ == stopbits_one_point_five)
|
||||
dcbSerialParams.StopBits = ONE5STOPBITS;
|
||||
else if (stopbits_ == stopbits_two)
|
||||
dcbSerialParams.StopBits = TWOSTOPBITS;
|
||||
else
|
||||
throw invalid_argument ("invalid stop bit");
|
||||
|
||||
// setup parity
|
||||
if (parity_ == parity_none) {
|
||||
dcbSerialParams.Parity = NOPARITY;
|
||||
} else if (parity_ == parity_even) {
|
||||
dcbSerialParams.Parity = EVENPARITY;
|
||||
} else if (parity_ == parity_odd) {
|
||||
dcbSerialParams.Parity = ODDPARITY;
|
||||
} else if (parity_ == parity_mark) {
|
||||
dcbSerialParams.Parity = MARKPARITY;
|
||||
} else if (parity_ == parity_space) {
|
||||
dcbSerialParams.Parity = SPACEPARITY;
|
||||
} else {
|
||||
throw invalid_argument ("invalid parity");
|
||||
}
|
||||
|
||||
// setup flowcontrol
|
||||
if (flowcontrol_ == flowcontrol_none) {
|
||||
dcbSerialParams.fOutxCtsFlow = false;
|
||||
dcbSerialParams.fRtsControl = 0x00;
|
||||
dcbSerialParams.fOutX = false;
|
||||
dcbSerialParams.fInX = false;
|
||||
}
|
||||
if (flowcontrol_ == flowcontrol_software) {
|
||||
dcbSerialParams.fOutxCtsFlow = false;
|
||||
dcbSerialParams.fRtsControl = 0x00;
|
||||
dcbSerialParams.fOutX = true;
|
||||
dcbSerialParams.fInX = true;
|
||||
}
|
||||
if (flowcontrol_ == flowcontrol_hardware) {
|
||||
dcbSerialParams.fOutxCtsFlow = true;
|
||||
dcbSerialParams.fRtsControl = 0x03;
|
||||
dcbSerialParams.fOutX = false;
|
||||
dcbSerialParams.fInX = false;
|
||||
}
|
||||
|
||||
// activate settings
|
||||
if (!SetCommState(fd_, &dcbSerialParams)){
|
||||
CloseHandle(fd_);
|
||||
THROW (IOException, "Error setting serial port settings.");
|
||||
}
|
||||
|
||||
// Setup timeouts
|
||||
COMMTIMEOUTS timeouts = {0};
|
||||
timeouts.ReadIntervalTimeout = timeout_.inter_byte_timeout;
|
||||
timeouts.ReadTotalTimeoutConstant = timeout_.read_timeout_constant;
|
||||
timeouts.ReadTotalTimeoutMultiplier = timeout_.read_timeout_multiplier;
|
||||
timeouts.WriteTotalTimeoutConstant = timeout_.write_timeout_constant;
|
||||
timeouts.WriteTotalTimeoutMultiplier = timeout_.write_timeout_multiplier;
|
||||
if (!SetCommTimeouts(fd_, &timeouts)) {
|
||||
THROW (IOException, "Error setting timeouts.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::close ()
|
||||
{
|
||||
if (is_open_ == true) {
|
||||
if (fd_ != INVALID_HANDLE_VALUE) {
|
||||
int ret;
|
||||
ret = CloseHandle(fd_);
|
||||
if (ret == 0) {
|
||||
stringstream ss;
|
||||
ss << "Error while closing serial port: " << GetLastError();
|
||||
THROW (IOException, ss.str().c_str());
|
||||
} else {
|
||||
fd_ = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
is_open_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Serial::SerialImpl::isOpen () const
|
||||
{
|
||||
return is_open_;
|
||||
}
|
||||
|
||||
size_t
|
||||
Serial::SerialImpl::available ()
|
||||
{
|
||||
if (!is_open_) {
|
||||
return 0;
|
||||
}
|
||||
COMSTAT cs;
|
||||
if (!ClearCommError(fd_, NULL, &cs)) {
|
||||
stringstream ss;
|
||||
ss << "Error while checking status of the serial port: " << GetLastError();
|
||||
THROW (IOException, ss.str().c_str());
|
||||
}
|
||||
return static_cast<size_t>(cs.cbInQue);
|
||||
}
|
||||
|
||||
bool
|
||||
Serial::SerialImpl::waitReadable (uint32_t /*timeout*/)
|
||||
{
|
||||
THROW (IOException, "waitReadable is not implemented on Windows.");
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::waitByteTimes (size_t /*count*/)
|
||||
{
|
||||
THROW (IOException, "waitByteTimes is not implemented on Windows.");
|
||||
}
|
||||
|
||||
size_t
|
||||
Serial::SerialImpl::read (uint8_t *buf, size_t size)
|
||||
{
|
||||
if (!is_open_) {
|
||||
throw PortNotOpenedException ("Serial::read");
|
||||
}
|
||||
DWORD bytes_read;
|
||||
if (!ReadFile(fd_, buf, static_cast<DWORD>(size), &bytes_read, NULL)) {
|
||||
stringstream ss;
|
||||
ss << "Error while reading from the serial port: " << GetLastError();
|
||||
THROW (IOException, ss.str().c_str());
|
||||
}
|
||||
return (size_t) (bytes_read);
|
||||
}
|
||||
|
||||
size_t
|
||||
Serial::SerialImpl::write (const uint8_t *data, size_t length)
|
||||
{
|
||||
if (is_open_ == false) {
|
||||
throw PortNotOpenedException ("Serial::write");
|
||||
}
|
||||
DWORD bytes_written;
|
||||
if (!WriteFile(fd_, data, static_cast<DWORD>(length), &bytes_written, NULL)) {
|
||||
stringstream ss;
|
||||
ss << "Error while writing to the serial port: " << GetLastError();
|
||||
THROW (IOException, ss.str().c_str());
|
||||
}
|
||||
return (size_t) (bytes_written);
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setPort (const string &port)
|
||||
{
|
||||
port_ = wstring(port.begin(), port.end());
|
||||
}
|
||||
|
||||
string
|
||||
Serial::SerialImpl::getPort () const
|
||||
{
|
||||
return string(port_.begin(), port_.end());
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setTimeout (serial::Timeout &timeout)
|
||||
{
|
||||
timeout_ = timeout;
|
||||
if (is_open_) {
|
||||
reconfigurePort ();
|
||||
}
|
||||
}
|
||||
|
||||
serial::Timeout
|
||||
Serial::SerialImpl::getTimeout () const
|
||||
{
|
||||
return timeout_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setBaudrate (unsigned long baudrate)
|
||||
{
|
||||
baudrate_ = baudrate;
|
||||
if (is_open_) {
|
||||
reconfigurePort ();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long
|
||||
Serial::SerialImpl::getBaudrate () const
|
||||
{
|
||||
return baudrate_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize)
|
||||
{
|
||||
bytesize_ = bytesize;
|
||||
if (is_open_) {
|
||||
reconfigurePort ();
|
||||
}
|
||||
}
|
||||
|
||||
serial::bytesize_t
|
||||
Serial::SerialImpl::getBytesize () const
|
||||
{
|
||||
return bytesize_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setParity (serial::parity_t parity)
|
||||
{
|
||||
parity_ = parity;
|
||||
if (is_open_) {
|
||||
reconfigurePort ();
|
||||
}
|
||||
}
|
||||
|
||||
serial::parity_t
|
||||
Serial::SerialImpl::getParity () const
|
||||
{
|
||||
return parity_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits)
|
||||
{
|
||||
stopbits_ = stopbits;
|
||||
if (is_open_) {
|
||||
reconfigurePort ();
|
||||
}
|
||||
}
|
||||
|
||||
serial::stopbits_t
|
||||
Serial::SerialImpl::getStopbits () const
|
||||
{
|
||||
return stopbits_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol)
|
||||
{
|
||||
flowcontrol_ = flowcontrol;
|
||||
if (is_open_) {
|
||||
reconfigurePort ();
|
||||
}
|
||||
}
|
||||
|
||||
serial::flowcontrol_t
|
||||
Serial::SerialImpl::getFlowcontrol () const
|
||||
{
|
||||
return flowcontrol_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::flush ()
|
||||
{
|
||||
if (is_open_ == false) {
|
||||
throw PortNotOpenedException ("Serial::flush");
|
||||
}
|
||||
FlushFileBuffers (fd_);
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::flushInput ()
|
||||
{
|
||||
THROW (IOException, "flushInput is not supported on Windows.");
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::flushOutput ()
|
||||
{
|
||||
THROW (IOException, "flushOutput is not supported on Windows.");
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::sendBreak (int /*duration*/)
|
||||
{
|
||||
THROW (IOException, "sendBreak is not supported on Windows.");
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setBreak (bool level)
|
||||
{
|
||||
if (is_open_ == false) {
|
||||
throw PortNotOpenedException ("Serial::setBreak");
|
||||
}
|
||||
if (level) {
|
||||
EscapeCommFunction (fd_, SETBREAK);
|
||||
} else {
|
||||
EscapeCommFunction (fd_, CLRBREAK);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setRTS (bool level)
|
||||
{
|
||||
if (is_open_ == false) {
|
||||
throw PortNotOpenedException ("Serial::setRTS");
|
||||
}
|
||||
if (level) {
|
||||
EscapeCommFunction (fd_, SETRTS);
|
||||
} else {
|
||||
EscapeCommFunction (fd_, CLRRTS);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setDTR (bool level)
|
||||
{
|
||||
if (is_open_ == false) {
|
||||
throw PortNotOpenedException ("Serial::setDTR");
|
||||
}
|
||||
if (level) {
|
||||
EscapeCommFunction (fd_, SETDTR);
|
||||
} else {
|
||||
EscapeCommFunction (fd_, CLRDTR);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Serial::SerialImpl::waitForChange ()
|
||||
{
|
||||
if (is_open_ == false) {
|
||||
throw PortNotOpenedException ("Serial::waitForChange");
|
||||
}
|
||||
DWORD dwCommEvent;
|
||||
|
||||
if (!SetCommMask(fd_, EV_CTS | EV_DSR | EV_RING | EV_RLSD)) {
|
||||
// Error setting communications mask
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!WaitCommEvent(fd_, &dwCommEvent, NULL)) {
|
||||
// An error occurred waiting for the event.
|
||||
return false;
|
||||
} else {
|
||||
// Event has occurred.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Serial::SerialImpl::getCTS ()
|
||||
{
|
||||
if (is_open_ == false) {
|
||||
throw PortNotOpenedException ("Serial::getCTS");
|
||||
}
|
||||
DWORD dwModemStatus;
|
||||
if (!GetCommModemStatus(fd_, &dwModemStatus)) {
|
||||
THROW (IOException, "Error getting the status of the CTS line.");
|
||||
}
|
||||
|
||||
return (MS_CTS_ON & dwModemStatus) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Serial::SerialImpl::getDSR ()
|
||||
{
|
||||
if (is_open_ == false) {
|
||||
throw PortNotOpenedException ("Serial::getDSR");
|
||||
}
|
||||
DWORD dwModemStatus;
|
||||
if (!GetCommModemStatus(fd_, &dwModemStatus)) {
|
||||
THROW (IOException, "Error getting the status of the DSR line.");
|
||||
}
|
||||
|
||||
return (MS_DSR_ON & dwModemStatus) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Serial::SerialImpl::getRI()
|
||||
{
|
||||
if (is_open_ == false) {
|
||||
throw PortNotOpenedException ("Serial::getRI");
|
||||
}
|
||||
DWORD dwModemStatus;
|
||||
if (!GetCommModemStatus(fd_, &dwModemStatus)) {
|
||||
THROW (IOException, "Error getting the status of the RI line.");
|
||||
}
|
||||
|
||||
return (MS_RING_ON & dwModemStatus) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Serial::SerialImpl::getCD()
|
||||
{
|
||||
if (is_open_ == false) {
|
||||
throw PortNotOpenedException ("Serial::getCD");
|
||||
}
|
||||
DWORD dwModemStatus;
|
||||
if (!GetCommModemStatus(fd_, &dwModemStatus)) {
|
||||
// Error in GetCommModemStatus;
|
||||
THROW (IOException, "Error getting the status of the CD line.");
|
||||
}
|
||||
|
||||
return (MS_RLSD_ON & dwModemStatus) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::readLock()
|
||||
{
|
||||
if (WaitForSingleObject(read_mutex, INFINITE) != WAIT_OBJECT_0) {
|
||||
THROW (IOException, "Error claiming read mutex.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::readUnlock()
|
||||
{
|
||||
if (!ReleaseMutex(read_mutex)) {
|
||||
THROW (IOException, "Error releasing read mutex.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::writeLock()
|
||||
{
|
||||
if (WaitForSingleObject(write_mutex, INFINITE) != WAIT_OBJECT_0) {
|
||||
THROW (IOException, "Error claiming write mutex.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::writeUnlock()
|
||||
{
|
||||
if (!ReleaseMutex(write_mutex)) {
|
||||
THROW (IOException, "Error releasing write mutex.");
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(_WIN32)
|
||||
|
||||
Reference in New Issue
Block a user