1 ///////////////////////////////////////////////////////////////////////////////
2 // BOSSA
3 //
4 // Copyright (c) 2011-2018, ShumaTech
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 // * Neither the name of the <organization> nor the
15 // names of its contributors may be used to endorse or promote products
16 // derived from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 // DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 ///////////////////////////////////////////////////////////////////////////////
29 #include "WinPortFactory.h"
30 #include "WinSerialPort.h"
31
32 #define USB_DEVICE_NAME "\\Device\\USB"
33
WinPortFactory()34 WinPortFactory::WinPortFactory() :
35 _devInfo(INVALID_HANDLE_VALUE), _cfgMgr(NULL), _devNode(NULL), _devNum(0)
36 {
37 }
38
~WinPortFactory()39 WinPortFactory::~WinPortFactory()
40 {
41 cleanup();
42 }
43
44 SerialPort::Ptr
create(const std::string & name)45 WinPortFactory::create(const std::string& name)
46 {
47 bool isUsb = false;
48 char szNtDeviceName[MAX_PATH];
49
50 if (QueryDosDevice(name.c_str(), szNtDeviceName, MAX_PATH))
51 {
52 if (strncmp(szNtDeviceName, USB_DEVICE_NAME, sizeof(USB_DEVICE_NAME) - 1) == 0)
53 {
54 isUsb = true;
55 }
56 }
57
58 return create(name, isUsb);
59 }
60
61 SerialPort::Ptr
create(const std::string & name,bool isUsb)62 WinPortFactory::create(const std::string& name, bool isUsb)
63 {
64 return SerialPort::Ptr(new WinSerialPort(name, isUsb));
65 }
66
67 void
cleanup()68 WinPortFactory::cleanup()
69 {
70 _devNum = 0;
71 _devNode = NULL;
72
73 if (_cfgMgr == NULL)
74 {
75 FreeLibrary(_cfgMgr);
76 _cfgMgr = NULL;
77 }
78
79 if (_devInfo != INVALID_HANDLE_VALUE)
80 {
81 SetupDiDestroyDeviceInfoList(_devInfo);
82 _devInfo = INVALID_HANDLE_VALUE;
83 }
84 }
85
86 std::string
error()87 WinPortFactory::error()
88 {
89 cleanup();
90 return end();
91 }
92
93 std::string
begin()94 WinPortFactory::begin()
95 {
96 DWORD size = 0;
97
98 if (_devInfo != INVALID_HANDLE_VALUE)
99 cleanup();
100
101 SetupDiClassGuidsFromNameA("Ports", 0, 0, &size);
102 if (size < 1)
103 return error();
104
105 GUID guids[size];
106
107 if (!SetupDiClassGuidsFromNameA("Ports", guids, size * sizeof(GUID), &size))
108 {
109 return error();
110 }
111
112 _devInfo = SetupDiGetClassDevs(guids, NULL, NULL, DIGCF_PRESENT);
113 if(_devInfo == INVALID_HANDLE_VALUE)
114 return error();
115
116 _cfgMgr = LoadLibrary("cfgmgr32");
117 if (!_cfgMgr)
118 return error();
119
120 _devNode = (CM_Open_DevNode_Key) GetProcAddress(_cfgMgr, "CM_Open_DevNode_Key");
121 if (!_devNode)
122 return error();
123
124 return next();
125 }
126
127 std::string
end()128 WinPortFactory::end()
129 {
130 return std::string();
131 }
132
133 std::string
next()134 WinPortFactory::next()
135 {
136 int rc;
137 BYTE devName[16];
138 SP_DEVINFO_DATA devData;
139 HKEY devKey;
140 DWORD len;
141
142 if (_devInfo == INVALID_HANDLE_VALUE)
143 return end();
144
145 while (1)
146 {
147 devData.cbSize = sizeof(SP_DEVINFO_DATA);
148 if (!SetupDiEnumDeviceInfo(_devInfo, _devNum, &devData))
149 return error();
150
151 rc = _devNode(devData.DevInst,
152 KEY_QUERY_VALUE,
153 0,
154 1,
155 &devKey,
156 0);
157
158 if (rc != ERROR_SUCCESS)
159 return error();
160
161 len = sizeof(devName);
162 rc = RegQueryValueEx(devKey,
163 "portname",
164 NULL,
165 NULL,
166 devName,
167 &len);
168
169 RegCloseKey(devKey);
170 if (rc != ERROR_SUCCESS)
171 return error();
172
173 _devNum++;
174
175 if (strncmp("COM", (char*) devName, 3) == 0)
176 break;
177 }
178
179 return std::string((char*) devName, len);
180 }
181
182 std::string
def()183 WinPortFactory::def()
184 {
185 return begin();
186 }
187
188