1 /******************************************************************************* 2 * 3 * FindAppUART.cpp - PC command line utility for enumerating MSP430 EVM's 4 * Application UARTs. 5 * 6 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the 18 * distribution. 19 * 20 * Neither the name of Texas Instruments Incorporated nor the names of 21 * its contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 * 36 ******************************************************************************/ 37 38 //------------------------------------------------------------------------------ 39 // Desc: PC command line utility for enumerating MSP430 EVM's Application UARTs. 40 // The application returns the COM port number of the first UART that is 41 // found. If this is successful the error code is set to '0'. In case of 42 // the UART string could not be determined '1' is returned. 43 // 44 // The code was developed with the Express Edition of Visual C++ 2008 45 // http://www.microsoft.com/express/ 46 // 47 // Ver.: 0.1 (February 2011) 48 // - Alpha version 49 // 50 // Auth: Andreas Dannenberg 51 // MSP430 Applications 52 // Texas Instruments, Inc. 53 //------------------------------------------------------------------------------ 54 55 // Windows Header Files 56 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff 57 // from Windows headers 58 #include <windows.h> 59 #include <tchar.h> 60 #include <shellapi.h> 61 #include <setupapi.h> // "setupapi.lib" must be linked 62 // to the project 63 // C Runtime Header Files 64 #include <stdlib.h> 65 #include <malloc.h> 66 #include <memory.h> 67 68 //------------------------------------------------------------------------------ 69 // DWORD WINAPI EnumComPorts(DWORD dwIndex, LPTSTR lptszName, 70 // DWORD dwNumOfElements) 71 // 72 // User-mode code fragment to identify attached VCP COMnn port[s] with a 73 // specific device instance ID based on USB VID and PID and returns the COMnn 74 // port that the OS embeds into the device instance ID. When called with 75 // dwIndex = 0, the function will enumerate all COMPORT class devices and 76 // return the name of the first one that was found. Subsequent calls using an 77 // incremented dwIndex parameter can be performed until ERROR_NO_MORE_ITEMS 78 // is returned. 79 // 80 // IN: dwIndex COMPORT class device # 0, 1, 2, ... to check 81 // dwNumOfElements The size of the lptszName buffer 82 // OUT: lptszName COMnn name of given device # 83 // return() ERROR_SUCCESS - lpszName is valid 84 // ERROR_NO_MORE_ITEMS - End of device list reached 85 //------------------------------------------------------------------------------ 86 DWORD WINAPI EnumComPorts(DWORD dwIndex, LPTSTR lptszName, DWORD dwNumOfElements) 87 { 88 HDEVINFO hDevInfo; 89 SP_DEVINFO_DATA DeviceInfoData; 90 DWORD i; 91 TCHAR *pcParse; 92 93 // Create a HDEVINFO with all present devices 94 hDevInfo = SetupDiGetClassDevs( 95 NULL, 96 0, // Enumerator 97 0, 98 DIGCF_PRESENT | DIGCF_ALLCLASSES); 99 100 if (INVALID_HANDLE_VALUE == hDevInfo) 101 { 102 return GetLastError(); 103 } 104 105 // Enumerate through all devices in set 106 DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 107 108 for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); i++) 109 { 110 LPTSTR buffer = NULL; 111 DWORD buffersize = 0; 112 113 // Get the device instance ID that is associated with the device information element 114 while (!SetupDiGetDeviceInstanceId( 115 hDevInfo, 116 &DeviceInfoData, 117 buffer, 118 buffersize, 119 &buffersize)) 120 { 121 if (buffer) 122 { 123 LocalFree(buffer); 124 } 125 126 if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) 127 { 128 // Change the buffer size. Double the size to avoid problems on 129 // W2K MBCS systems per KB 888609. 130 buffer = (LPTSTR)LocalAlloc(LPTR, buffersize * 2); 131 } 132 else 133 { 134 // Error: could not get device instance ID 135 // Cleanup and return error code 136 SetupDiDestroyDeviceInfoList(hDevInfo); 137 return GetLastError(); 138 } 139 } 140 141 if (buffer) 142 { 143 // Look for the "Application UART" of common MSP430 EVMs. The application UART 144 // has an USB VID of 0x0451 (Texas Instruments) and an PID of 0xF432. 145 const TCHAR testval[] = _T("USB\\VID_0451&PID_F432&MI_00"); 146 147 if (NULL != _tcsstr(buffer, testval)) 148 { 149 TCHAR szFriendlyName[MAX_PATH]; 150 151 if (SetupDiGetDeviceRegistryProperty( 152 hDevInfo, 153 &DeviceInfoData, 154 SPDRP_FRIENDLYNAME, 155 NULL, 156 (PBYTE)szFriendlyName, 157 sizeof(szFriendlyName) - 1, 158 NULL)) 159 { 160 // Check if we have reached the dwIndex-th element, if not keep looking 161 if (dwIndex == 0) 162 { 163 // Find pointer to "COM" substring (secure) 164 szFriendlyName[sizeof(szFriendlyName) - 1] = 0x00; 165 pcParse = _tcsstr(szFriendlyName, _T("COM")); 166 167 if (pcParse != NULL) 168 { 169 // Zero-terminate COM port string after last digit 170 if (!isdigit(pcParse[4])) { 171 pcParse[4] = 0; 172 } 173 else if (!isdigit(pcParse[5])) { 174 pcParse[5] = 0; 175 } 176 else { 177 pcParse[6] = 0; 178 } 179 180 // Pass string to the return parameter 181 _tcscpy_s(lptszName, dwNumOfElements, pcParse); 182 183 // Cleanup 184 SetupDiDestroyDeviceInfoList(hDevInfo); 185 186 return ERROR_SUCCESS; 187 } 188 } 189 else 190 { 191 dwIndex--; 192 } 193 } 194 } 195 } 196 } 197 198 // Cleanup 199 SetupDiDestroyDeviceInfoList(hDevInfo); 200 201 return ERROR_NO_MORE_ITEMS; 202 } 203 204 //------------------------------------------------------------------------------ 205 // Main application entry point. Simply return the first Application UART 206 // COM port that was found to STDOUT. 207 //------------------------------------------------------------------------------ 208 int _tmain(int argc, _TCHAR* argv[]) 209 { 210 TCHAR szDeviceName[MAX_PATH]; 211 DWORD dwReturnValue; 212 213 dwReturnValue = EnumComPorts(0, szDeviceName, _countof(szDeviceName)); 214 215 if (dwReturnValue == ERROR_SUCCESS) { 216 _ftprintf_s(stdout, _T("%s\r\n"), szDeviceName); 217 return 0; 218 } 219 220 return 1; 221 }