1 /**
2 @file ConnectionEVB7COM.cpp
3 @author Lime Microsystems
4 @brief Implementation of EVB7 connection of serial COM port.
5 */
6
7 #include "ConnectionEVB7COM.h"
8 #include <fstream>
9 #include <iostream>
10
11 using namespace std;
12 using namespace lime;
13
14 static const int comBaudrate = 9600;
15
16 //! make a static-initialized entry in the registry
__loadConnectionEVB7COMEntry(void)17 void __loadConnectionEVB7COMEntry(void) //TODO fixme replace with LoadLibrary/dlopen
18 {
19 static ConnectionEVB7COMEntry EVB7COMEntry;
20 }
21
ConnectionEVB7COMEntry(void)22 ConnectionEVB7COMEntry::ConnectionEVB7COMEntry(void):
23 ConnectionRegistryEntry("EVB7COM")
24 {
25 return;
26 }
27
enumerate(const ConnectionHandle & hint)28 std::vector<ConnectionHandle> ConnectionEVB7COMEntry::enumerate(const ConnectionHandle &hint)
29 {
30 std::vector<ConnectionHandle> result;
31 auto comPortList = this->FindAllComPorts();
32 auto availableComms = this->FilterDeviceList(comPortList);
33 for (const auto &comName : availableComms)
34 {
35 ConnectionHandle handle;
36 handle.media = "COM";
37 handle.name = "EVB7 ("+comName+")";
38 handle.addr = comName;
39 if(hint.addr.length() == 0 || hint.addr == handle.addr)
40 result.push_back(handle);
41 }
42 return result;
43 }
44
make(const ConnectionHandle & handle)45 IConnection *ConnectionEVB7COMEntry::make(const ConnectionHandle &handle)
46 {
47 return new ConnectionEVB7COM(handle.addr.c_str(), comBaudrate);
48 }
49
FindAllComPorts()50 std::vector<std::string> ConnectionEVB7COMEntry::FindAllComPorts()
51 {
52 std::vector<std::string> comPortList;
53 #ifndef __unix__
54 HKEY hSERIALCOMM;
55 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hSERIALCOMM) == ERROR_SUCCESS)
56 {
57 // Get the max value name and max value lengths
58 DWORD dwMaxValueNameLen;
59 DWORD dwMaxValueLen;
60 DWORD dwQueryInfo = RegQueryInfoKey(hSERIALCOMM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL);
61 if (dwQueryInfo == ERROR_SUCCESS)
62 {
63 DWORD dwMaxValueNameSizeInChars = dwMaxValueNameLen + 1;
64 // Include space for the NULL terminator
65 DWORD dwMaxValueNameSizeInBytes = dwMaxValueNameSizeInChars*sizeof(TCHAR);
66 DWORD dwMaxValueDataSizeInChars = dwMaxValueLen / sizeof(TCHAR) + 1;
67 // Include space for the NULL terminator
68 DWORD dwMaxValueDataSizeInBytes = dwMaxValueDataSizeInChars*sizeof(TCHAR);
69
70 // Allocate some space for the value name and value data
71 TCHAR* szValueName = new TCHAR[dwMaxValueNameSizeInChars];
72 TCHAR* byValue = new TCHAR[dwMaxValueDataSizeInBytes];
73 if (szValueName && byValue)
74 {
75 // Enumerate all the values underneath HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
76 DWORD dwIndex = 0;
77 DWORD dwType;
78 DWORD dwValueNameSize = dwMaxValueNameSizeInChars;
79 DWORD dwDataSize = dwMaxValueDataSizeInBytes;
80 memset(szValueName, 0, dwMaxValueNameSizeInBytes);
81 memset(byValue, 0, dwMaxValueDataSizeInBytes);
82 LONG nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, (LPBYTE)byValue, &dwDataSize);
83 while (nEnum == ERROR_SUCCESS)
84 {
85 // If the value is of the correct type, then add it to the array
86 if (dwType == REG_SZ)
87 {
88 char portname[512];
89 TCHAR* szPort = byValue;
90 int nUserNameLenUnicode = lstrlen( szPort ); // Convert all UNICODE characters
91 int nUserNameLen = WideCharToMultiByte( CP_ACP, // ANSI Code Page
92 0, // No special handling of unmapped chars
93 (LPCWSTR)szPort, // wide-character string to be converted
94 nUserNameLenUnicode,
95 NULL, 0, // No output buffer since we are calculating length
96 NULL, NULL ); // Unrepresented char replacement - Use Default
97 TCHAR* pszUserName = new TCHAR[ nUserNameLen ]; // nUserNameLen includes the NULL character
98 WideCharToMultiByte( CP_ACP, // ANSI Code Page
99 0, // No special handling of unmapped chars
100 (LPCWSTR)szPort, // wide-character string to be converted
101 nUserNameLenUnicode,
102 portname,
103 nUserNameLen,
104 NULL, NULL ); // Unrepresented char replacement - Use Default
105 portname[nUserNameLen] = 0;
106 #ifdef UNICODE
107 comPortList.push_back(portname);
108 #else
109 comPortList.push_back(szPort);
110 #endif
111 }
112 // Prepare for the next time around
113 dwValueNameSize = dwMaxValueNameSizeInChars;
114 dwDataSize = dwMaxValueDataSizeInBytes;
115 memset(szValueName, 0, dwMaxValueNameSizeInBytes);
116 memset(byValue, 0, dwMaxValueDataSizeInBytes);
117 ++dwIndex;
118 nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, (LPBYTE)byValue, &dwDataSize);
119 }
120 }
121 delete szValueName;
122 delete byValue;
123 }
124 // Close the registry key now that we are finished with it
125 RegCloseKey(hSERIALCOMM);
126
127 if (dwQueryInfo != ERROR_SUCCESS)
128 SetLastError(dwQueryInfo);
129 }
130 #else
131 char tempBuffer[256];
132 string result = "";
133 if (system( "ls /dev | grep ttyACM > /tmp/foundSerialPorts.txt") == -1)
134 return comPortList;
135
136 fstream fin;
137 fin.open("/tmp/foundSerialPorts.txt", ios::in);
138 while(!fin.eof())
139 {
140 fin.getline(tempBuffer, 256);
141 result = "/dev/";
142 result.append(tempBuffer);
143 if( strlen(tempBuffer) > 3 ) //longer than tty
144 comPortList.push_back(result);
145 }
146 fin.close();
147 #endif
148
149 return comPortList;
150 }
151
FilterDeviceList(const std::vector<std::string> & comPortList)152 std::vector<std::string> ConnectionEVB7COMEntry::FilterDeviceList(const std::vector<std::string> &comPortList)
153 {
154 std::vector<std::string> deviceNames;
155
156 string comName;
157 for(unsigned int i=0; i<comPortList.size(); i++)
158 {
159 comName = comPortList[i];
160
161 //when not on unix, perform a test open to validate the port
162 #ifndef __unix__
163 ConnectionEVB7COM testConn(comName.c_str(), comBaudrate);
164 if (testConn.IsOpen()) deviceNames.push_back(comName);
165 #else
166 deviceNames.push_back(comName);
167 #endif
168 }
169 return deviceNames;
170 }
171