You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					170 lines
				
				5.7 KiB
			
		
		
			
		
	
	
					170 lines
				
				5.7 KiB
			| 
								 
											6 years ago
										 
									 | 
							
								#include "stdafx.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <SetupAPI.h>
							 | 
						||
| 
								 | 
							
								#include <Devpkey.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <unordered_map>
							 | 
						||
| 
								 | 
							
								#include <string>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <winusb.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "device.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								using namespace panda;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
							 | 
						||
| 
								 | 
							
								tstring GetLastErrorAsString(){
							 | 
						||
| 
								 | 
							
									//Get the error message, if any.
							 | 
						||
| 
								 | 
							
									DWORD errorMessageID = ::GetLastError();
							 | 
						||
| 
								 | 
							
									if (errorMessageID == 0)
							 | 
						||
| 
								 | 
							
										return tstring(); //No error message has been recorded
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									_TCHAR *messageBuffer = nullptr;
							 | 
						||
| 
								 | 
							
									size_t size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
							 | 
						||
| 
								 | 
							
										NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (_TCHAR*)&messageBuffer, 0, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									tstring message(messageBuffer, size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//Free the buffer.
							 | 
						||
| 
								 | 
							
									LocalFree(messageBuffer);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return message;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								std::unordered_map<std::string, tstring> panda::detect_pandas() {
							 | 
						||
| 
								 | 
							
									HDEVINFO                        deviceInfo;
							 | 
						||
| 
								 | 
							
									HRESULT                         hr;
							 | 
						||
| 
								 | 
							
									SP_DEVINFO_DATA					deviceInfoData;
							 | 
						||
| 
								 | 
							
									SP_DEVICE_INTERFACE_DATA		interfaceData;
							 | 
						||
| 
								 | 
							
									unsigned int					deviceIndex;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									std::unordered_map<std::string, tstring> map_sn_to_devpath;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									deviceInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_panda,
							 | 
						||
| 
								 | 
							
										NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); //DIGCF_ALLCLASSES
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (deviceInfo == INVALID_HANDLE_VALUE) {
							 | 
						||
| 
								 | 
							
										hr = HRESULT_FROM_WIN32(GetLastError());
							 | 
						||
| 
								 | 
							
										_tprintf(_T("Failed to get dev handle. HR: %d\n"), hr);
							 | 
						||
| 
								 | 
							
										return map_sn_to_devpath;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA));
							 | 
						||
| 
								 | 
							
									deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
							 | 
						||
| 
								 | 
							
									deviceIndex = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									while (SetupDiEnumDeviceInfo(deviceInfo, deviceIndex, &deviceInfoData)) {
							 | 
						||
| 
								 | 
							
										deviceIndex++;
							 | 
						||
| 
								 | 
							
										_tprintf(_T("Device info index %d\n"), deviceIndex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
							 | 
						||
| 
								 | 
							
										if (SetupDiEnumDeviceInterfaces(deviceInfo, &deviceInfoData,
							 | 
						||
| 
								 | 
							
											&GUID_DEVINTERFACE_panda, 0, &interfaceData) == FALSE) {
							 | 
						||
| 
								 | 
							
											_tprintf(_T("    Got unexpected error while accessing interface %d\n"), GetLastError());
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										DWORD requiredLength;
							 | 
						||
| 
								 | 
							
										if (SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, NULL, 0, &requiredLength, NULL) == FALSE
							 | 
						||
| 
								 | 
							
											&& ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
							 | 
						||
| 
								 | 
							
											_tprintf(_T("    Got unexpected error while reading interface details %d\n"), GetLastError());
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LMEM_FIXED, requiredLength);
							 | 
						||
| 
								 | 
							
										if (NULL == detailData) {
							 | 
						||
| 
								 | 
							
											_tprintf(_T("    Failed to allocate %d bytes for interface data\n"), requiredLength);
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										DWORD length = requiredLength;
							 | 
						||
| 
								 | 
							
										if (SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, detailData, length, &requiredLength, NULL) == FALSE) {
							 | 
						||
| 
								 | 
							
											_tprintf(_T("    Got unexpected error while reading interface details (2nd time) %d. Msg: '%s'\n"),
							 | 
						||
| 
								 | 
							
												GetLastError(), GetLastErrorAsString().c_str());
							 | 
						||
| 
								 | 
							
											LocalFree(detailData);
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//_tprintf(_T("    Path: '%s'\n"), detailData->DevicePath);
							 | 
						||
| 
								 | 
							
										HANDLE deviceHandle = CreateFile(detailData->DevicePath,
							 | 
						||
| 
								 | 
							
											GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
							 | 
						||
| 
								 | 
							
											NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (INVALID_HANDLE_VALUE == deviceHandle) {
							 | 
						||
| 
								 | 
							
											_tprintf(_T("    Error opening Device Handle %d. Msg: '%s'\n"),
							 | 
						||
| 
								 | 
							
												GetLastError(), GetLastErrorAsString().c_str());
							 | 
						||
| 
								 | 
							
											LocalFree(detailData);
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										WINUSB_INTERFACE_HANDLE winusbHandle;
							 | 
						||
| 
								 | 
							
										if (WinUsb_Initialize(deviceHandle, &winusbHandle) == FALSE) {
							 | 
						||
| 
								 | 
							
											_tprintf(_T("    Error initializing WinUSB %d. Msg: '%s'\n"),
							 | 
						||
| 
								 | 
							
												GetLastError(), GetLastErrorAsString().c_str());
							 | 
						||
| 
								 | 
							
											CloseHandle(deviceHandle);
							 | 
						||
| 
								 | 
							
											LocalFree(detailData);
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										USB_DEVICE_DESCRIPTOR deviceDesc;
							 | 
						||
| 
								 | 
							
										unsigned long lengthReceived;
							 | 
						||
| 
								 | 
							
										if (WinUsb_GetDescriptor(winusbHandle, USB_DEVICE_DESCRIPTOR_TYPE, 0, 0,
							 | 
						||
| 
								 | 
							
											(PBYTE)&deviceDesc, sizeof(deviceDesc), &lengthReceived) == FALSE
							 | 
						||
| 
								 | 
							
											|| lengthReceived != sizeof(deviceDesc)) {
							 | 
						||
| 
								 | 
							
											_tprintf(_T("    Error getting device descriptor %d. Msg: '%s'\n"),
							 | 
						||
| 
								 | 
							
												GetLastError(), GetLastErrorAsString().c_str());
							 | 
						||
| 
								 | 
							
											WinUsb_Free(winusbHandle);
							 | 
						||
| 
								 | 
							
											CloseHandle(deviceHandle);
							 | 
						||
| 
								 | 
							
											LocalFree(detailData);
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										#define SNDESCLEN 64
							 | 
						||
| 
								 | 
							
										PUSB_STRING_DESCRIPTOR psnDesc = (PUSB_STRING_DESCRIPTOR)LocalAlloc(LMEM_FIXED, SNDESCLEN);
							 | 
						||
| 
								 | 
							
										if (NULL == psnDesc) {
							 | 
						||
| 
								 | 
							
											_tprintf(_T("    Failed to allocate %d bytes for sn data\n"), SNDESCLEN);
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (WinUsb_GetDescriptor(winusbHandle, USB_STRING_DESCRIPTOR_TYPE, deviceDesc.iSerialNumber,
							 | 
						||
| 
								 | 
							
											0x0409 /*Eng*/, (PBYTE)psnDesc, SNDESCLEN, &lengthReceived) == FALSE || lengthReceived == 0) {
							 | 
						||
| 
								 | 
							
											_tprintf(_T("    Error getting serial number %d. Msg: '%s'\n"),
							 | 
						||
| 
								 | 
							
												GetLastError(), GetLastErrorAsString().c_str());
							 | 
						||
| 
								 | 
							
											LocalFree(psnDesc);
							 | 
						||
| 
								 | 
							
											WinUsb_Free(winusbHandle);
							 | 
						||
| 
								 | 
							
											CloseHandle(deviceHandle);
							 | 
						||
| 
								 | 
							
											LocalFree(detailData);
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										//The minus 2 is for the two numbers, not the null term.
							 | 
						||
| 
								 | 
							
										psnDesc->bString[(psnDesc->bLength - 2) / sizeof(_TCHAR)] = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										char w_to_m_buff[256];
							 | 
						||
| 
								 | 
							
										size_t mbuff_len;
							 | 
						||
| 
								 | 
							
										if (wcstombs_s(&mbuff_len, w_to_m_buff, sizeof(w_to_m_buff), psnDesc->bString, 24) != 0) {
							 | 
						||
| 
								 | 
							
											_tprintf(_T("    Error generating mb SN string %d. Msg: '%s'\n"),
							 | 
						||
| 
								 | 
							
												GetLastError(), GetLastErrorAsString().c_str());
							 | 
						||
| 
								 | 
							
											LocalFree(psnDesc);
							 | 
						||
| 
								 | 
							
											WinUsb_Free(winusbHandle);
							 | 
						||
| 
								 | 
							
											CloseHandle(deviceHandle);
							 | 
						||
| 
								 | 
							
											LocalFree(detailData);
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										std::string serialnum(w_to_m_buff, mbuff_len-1);
							 | 
						||
| 
								 | 
							
										printf("    Device found: seriallen: %d; serial: %s\n", lengthReceived, serialnum.c_str());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										map_sn_to_devpath[serialnum] = tstring(detailData->DevicePath);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										LocalFree(psnDesc);
							 | 
						||
| 
								 | 
							
										WinUsb_Free(winusbHandle);
							 | 
						||
| 
								 | 
							
										CloseHandle(deviceHandle);
							 | 
						||
| 
								 | 
							
										LocalFree(detailData);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if(deviceInfo)
							 | 
						||
| 
								 | 
							
										SetupDiDestroyDeviceInfoList(deviceInfo);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return map_sn_to_devpath;
							 | 
						||
| 
								 | 
							
								}
							 |