openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
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.
 
 
 
 
 
 

169 lines
5.7 KiB

#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;
}