diff --git a/EDUReViver.suo b/EDUReViver.suo
index bdb45b2..60405fc 100644
Binary files a/EDUReViver.suo and b/EDUReViver.suo differ
diff --git a/EDUReViver/EDUReViver.vcxproj b/EDUReViver/EDUReViver.vcxproj
index b9779c6..5cdc8dc 100644
--- a/EDUReViver/EDUReViver.vcxproj
+++ b/EDUReViver/EDUReViver.vcxproj
@@ -168,6 +168,7 @@
+
diff --git a/EDUReViver/EDUReViver.vcxproj.filters b/EDUReViver/EDUReViver.vcxproj.filters
index 777264a..37f6000 100644
--- a/EDUReViver/EDUReViver.vcxproj.filters
+++ b/EDUReViver/EDUReViver.vcxproj.filters
@@ -50,5 +50,8 @@
Header Files
+
+ Header Files
+
\ No newline at end of file
diff --git a/EDUReViver/main.cpp b/EDUReViver/main.cpp
index 5a83f2a..290d8cb 100644
--- a/EDUReViver/main.cpp
+++ b/EDUReViver/main.cpp
@@ -106,8 +106,7 @@ enum payloadmode {
};
-#define CLOSE_AND_EXIT(code) freeJLinks(devvec);\
- UnloadWinusb();\
+#define CLOSE_AND_EXIT(code) UnloadWinusb();\
return code;
void printmismatch(const char* name, bool mismatch)
@@ -119,6 +118,8 @@ void printmismatch(const char* name, bool mismatch)
}
}
+
+
int main(int argc, char * argv[])
{
//#ifdef _DEBUG
@@ -150,25 +151,40 @@ int main(int argc, char * argv[])
}
}
if (payloadname == 0) {
- printf("V10ReViver -run [options]\n");
+ printf("EDUReViver -run [options]\n");
return -1;
}
if (LoadWinusb() != 0) {
printf("No WinUSB support because WinUSB.dll is corrupt or missing.\n");;
}
- JLinkDevVec devvec;
- if (!getJLinks(devvec)) {
+ startupKeeper();
+ atexit(shutdownKeeper);
+ JLinkInfoVec infovec;
+ if (!LinkKeeper::getJLinksSnap(infovec)) {
errprintf("Failed to find device!\n");
CLOSE_AND_EXIT(0);
- } else if (devvec.size() > 1) {
- errprintf("Only support one device, please unplug other probes!\n");
- CLOSE_AND_EXIT(0);
+ } else if (infovec.size() > 1) {
+ int i = 1;
+ for (JLinkInfoVec::const_iterator it = infovec.begin(); it != infovec.end(); it++, i++) {
+ printf("%d: %s [%d] sn %d%s\n", i, it->locationInfo.hubName.c_str(), it->locationInfo.devPort, it->winSerial, it->isWinusb?" WinUSB":"");
+ }
+ printf("Input device index: ");
+ scanf_s("%d", &i);
+ getchar();
+ if (1 <= i && i <= infovec.size()) {
+ LinkKeeper::selectDevice(infovec.at(i - 1).locationInfo);
+ } else {
+ errprintf("Out of index!\n");
+ CLOSE_AND_EXIT(0);
+ }
+ } else {
+ LinkKeeper::selectDevice(infovec.at(0).locationInfo); // one device
}
uint8_t dataBuffer[512] = {0};
bool isv10 = false;
- jlinkLoopReadFirmwareVersion(&devvec[0], dataBuffer);
+ LinkKeeper::loopReadFirmwareVersion(dataBuffer);
dataBuffer[0x70] = 0;
//isv9 = strstr((const char*)dataBuffer, "V9") != 0;
isv10 = (strstr((const char*)dataBuffer, "V10") != 0) || (strstr((const char*)dataBuffer, "V11") != 0) || (strstr((const char*)dataBuffer, "V12") != 0);
@@ -182,7 +198,7 @@ int main(int argc, char * argv[])
errprintf("Only support v10,v11,v12 devices.\n");
CLOSE_AND_EXIT(0);
}
- // check genius hardware
+ // check genuine hardware
const patcher_config* config = find_patcher_config((char*)dataBuffer);
uint32_t sn, snchecksum;
uint8_t snuidbuf[36];
@@ -191,7 +207,7 @@ int main(int argc, char * argv[])
bool touchfeatures = _stricmp(payloadname, "revive") == 0;
bool touchsn = _stricmp(payloadname, "setsn") == 0;
bool touchcrp = _stricmp(payloadname, "swd") == 0;
- if (jlinkCommandReadOTS(&devvec[0], dataBuffer)) {
+ if (LinkKeeper::commandReadOTS(dataBuffer)) {
sn = *(uint32_t*)dataBuffer;
snchecksum = *(uint32_t*)(dataBuffer + 4);
otssign = dataBuffer + 0x100;
@@ -207,7 +223,7 @@ int main(int argc, char * argv[])
bool otssignok = false;
void* myapp = 0;
int applen = 0;
- if (jlinkCommandReadUID(&devvec[0], &uidlen, &snuidbuf[4])) {
+ if (LinkKeeper::commandReadUID(&uidlen, &snuidbuf[4])) {
char* uidstr = base64_encode(&snuidbuf[4], uidlen);
char* signstr = base64_encode((uint8_t*)otssign, 0x100);
char* reply = 0;
@@ -249,7 +265,7 @@ int main(int argc, char * argv[])
uint32_t dumpsize = config?0x8000:0x80000;
// dump bootloader/firmware and parse
char* fwdump = (char*)malloc(dumpsize);
- if (jlinkDumpFullFirmware(&devvec[0], 0x1A000000, dumpsize, fwdump)) {
+ if (LinkKeeper::dumpFullFirmware(0x1A000000, dumpsize, fwdump)) {
bool bootloaderok = is_offical_bootloader(fwdump);
if (touchcrp) {
printCRPlevel(*(uint32_t*)&fwdump[0x2FC]);
@@ -289,7 +305,7 @@ int main(int argc, char * argv[])
}
uint32_t oldif;
- if (jlinkCommandSendSelectInterface(&devvec[0], 3, &oldif)) {
+ if (LinkKeeper::commandSendSelectInterface(3, &oldif)) {
printf("Change interface: %d -> 3\n", oldif);
} else {
errprintf("Select interface failed!\n");
@@ -334,7 +350,7 @@ int main(int argc, char * argv[])
*(uint32_t*)&m4rxret[0x28] = config->lr | 1; // 要返回dispatchcmd
m4rxcmd = assembly_cmd_payload(&cmdlen, m4rxret, sizeof(m4rxret), config, 0);
}
- jlinkSendCommand(&devvec[0], m4rxcmd, cmdlen, &readed, sizeof(readed));
+ LinkKeeper::sendCommand(m4rxcmd, cmdlen, &readed, sizeof(readed));
free(m4rxcmd);
} else {
// 双次溢出
@@ -347,7 +363,7 @@ int main(int argc, char * argv[])
};
*(uint32_t*)&patcher[0x20] = config->lr + 1; // 第一次要返回dispatchcmd
cmd_fine_write_read* patchercmd = assembly_cmd_payload(&cmdlen, patcher, sizeof(patcher), config, 0);
- jlinkSendCommand(&devvec[0], patchercmd, cmdlen, &readed, sizeof(readed));
+ LinkKeeper::sendCommand(patchercmd, cmdlen, &readed, sizeof(readed));
free(patchercmd);
M0patched = true;
// 此时代码可以使用连续的0x2C/0x28内容, 其他注意事项同上
@@ -376,7 +392,7 @@ int main(int argc, char * argv[])
*(uint32_t*)&m0ldr[0x28] = config->lr | 1;
ldrcmd = assembly_cmd_payload(&cmdlen, m0ldr, sizeof(m0ldr), config, -0x18);
}
- jlinkSendCommand(&devvec[0], ldrcmd, cmdlen, NULL, 0);
+ LinkKeeper::sendCommand(ldrcmd, cmdlen, NULL, 0);
free(ldrcmd);
}
// SES固件 R4~R6无可用空间情况的第二次溢出, 为了兼容未来固件(但不能不知R4~R6值)
@@ -389,7 +405,7 @@ int main(int argc, char * argv[])
*(uint32_t*)&m4rxret[0x1C] = config->usbrx | 1;
*(uint32_t*)&m4rxret[0x20] = config->lr | 1; // 要返回dispatchcmd
cmd_fine_write_read* m4rxcmd = assembly_cmd_payload(&cmdlen, m4rxret, sizeof(m4rxret), config, 0);
- jlinkSendCommand(&devvec[0], m4rxcmd, cmdlen, &readed, sizeof(readed));
+ LinkKeeper::sendCommand(m4rxcmd, cmdlen, &readed, sizeof(readed));
free(m4rxcmd);
}
}
@@ -400,20 +416,21 @@ int main(int argc, char * argv[])
// 超写模式, 不需接收器部分, 最后需重启
// 特殊payload: 不带返回指针, 单2C/28 gap
cmd_fine_write_read* m4loopcmd = assembly_cmd_payload(&cmdlen, myapp, applen, config, -0x18);
- jlinkSendCommand(&devvec[0], m4loopcmd, cmdlen, NULL, 0);
+ LinkKeeper::prepareReconnect();
+ LinkKeeper::sendCommand(m4loopcmd, cmdlen, NULL, 0);
free(m4loopcmd);
} else {
// 填充到800发出(因为接收器要接满800,可以改loader变为400/200)
int applenfull = 0x800;
myapp = realloc(myapp, 0x800);
memset((char*)myapp + applen, 0, applenfull - applen);
- jlinkSendCommand(&devvec[0], myapp, applenfull, NULL, 0);
+ LinkKeeper::sendCommand(myapp, applenfull, NULL, 0);
}
free(myapp);
// 清理步骤, 如果打过M0补丁, 则恢复补丁, 重启版除外, 等他重启
if (M0patched && mode != pmM4Reset) {
uint32_t oldif2;
- if (jlinkCommandSendSelectInterface(&devvec[0], oldif, &oldif2)) {
+ if (LinkKeeper::commandSendSelectInterface(oldif, &oldif2)) {
printf("Change interface: %d -> %d\n", oldif2, oldif);
} else {
errprintf("Select interface failed!\n");
@@ -421,19 +438,13 @@ int main(int argc, char * argv[])
}
}
if (mode == pmM4Reset) {
- freeJLinks(devvec);
-
printf("Waiting device re-connect...\n");
- SleepEx(5000, TRUE);
- if (!getJLinks(devvec)) {
- errprintf("Failed to find device!\n");
- return 0;
- } else if (devvec.size() > 1) {
- errprintf("Only support single device, please unplug other probes!\n");
+ if (!LinkKeeper::waitReconnect(5000, 100)) {
+ errprintf("Failed to reconnect in 5 sec!\n");
CLOSE_AND_EXIT(0);
}
- jlinkLoopReadFirmwareVersion(&devvec[0], dataBuffer);
+ LinkKeeper::loopReadFirmwareVersion(dataBuffer);
if (is_BTL_version((char*)dataBuffer)) {
printf("Found BTL Mode.\n");
} else {
@@ -441,7 +452,7 @@ int main(int argc, char * argv[])
}
quickdump(0, dataBuffer, 0x70);
}
- if ((touchfeatures || touchsn) && jlinkCommandReadOTS(&devvec[0], dataBuffer)) {
+ if ((touchfeatures || touchsn) && LinkKeeper::commandReadOTS(dataBuffer)) {
if (touchsn) {
sn = *(uint32_t*)dataBuffer;
snchecksum = *(uint32_t*)(dataBuffer + 4);
@@ -455,12 +466,12 @@ int main(int argc, char * argv[])
}
if (touchcrp) {
uint32_t crp;
- if (jlinkDumpFullFirmware(&devvec[0], 0x1A0002FC, 4, &crp)) {
+ if (LinkKeeper::dumpFullFirmware(0x1A0002FC, 4, &crp)) {
printCRPlevel(crp);
}
}
- freeJLinks(devvec);
+ shutdownKeeper();
UnloadWinusb();
#ifdef _DEBUG
_getch();
diff --git a/EDUReViver/usbconn.cpp b/EDUReViver/usbconn.cpp
index 1314820..adc6373 100644
--- a/EDUReViver/usbconn.cpp
+++ b/EDUReViver/usbconn.cpp
@@ -3,7 +3,9 @@
#include
#include
//#include
-#include
+//#include
+#include
+#include
#include "usbconn.h"
#include "addon_func.h"
@@ -78,9 +80,159 @@ int UnloadWinusb()
return 0;
}
+void extractDevID(char *devid, size_t len, const char *devpath);
+bool lookupTopSeggerDevID(DEVINST* devinst, uint16_t vid, char* devid, char* hubid, char* hubname, int* port);
+size_t g_recvpos = 0;
+
+void hublocation::clear()
+{
+ hubDevID.clear();
+ hubName.clear();
+ devPort = 0;
+}
+
+void JlinkDevice::open()
+{
+ if (deviceFile == INVALID_HANDLE_VALUE) {
+ if (isWinusb) {
+ HANDLE deviceFile = CreateFileA(devicePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
+ if (deviceFile == INVALID_HANDLE_VALUE) {
+ return;
+ }
+
+ WINUSB_INTERFACE_HANDLE winusbHandle;
+ if (!WinUsb_Initialize(deviceFile, &winusbHandle)) {
+ printf("Failed to invoke WinUsb_Initialize, last error %lu\n", GetLastError());
+ CloseHandle(deviceFile);
+ return;
+ }
+ uint8_t desc[0x200];
+ ULONG desclen = 0x200;
+ if (!WinUsb_GetDescriptor(winusbHandle, USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, desc, desclen, &desclen)) {
+ printf("Failed to invoke WinUsb_GetDescriptor, last error %lu\n", GetLastError());
+ CloseHandle(deviceFile);
+ return;
+ }
+ uint8_t inep = 0, outep = 0;
+ PUSB_CONFIGURATION_DESCRIPTOR confdesc = (PUSB_CONFIGURATION_DESCRIPTOR)desc;
+ PUSB_INTERFACE_DESCRIPTOR ifdesc = (PUSB_INTERFACE_DESCRIPTOR)&desc[confdesc->bLength];
+ for (int i = 0; i < confdesc->bNumInterfaces; i++, ifdesc++) {
+ PUSB_ENDPOINT_DESCRIPTOR epdesc = (PUSB_ENDPOINT_DESCRIPTOR)((char*)ifdesc + ifdesc->bLength);
+ for (int j = 0; j < ifdesc->bNumEndpoints; j++, epdesc++) {
+ if ((epdesc->bmAttributes & 3) == 2) {
+ if (epdesc->bEndpointAddress & 0x80) {
+ inep = epdesc->bEndpointAddress; // 0x81
+ } else {
+ outep = epdesc->bEndpointAddress; // 0x01
+ }
+ }
+ }
+ if (inep && outep) {
+ break;
+ }
+ }
+ CHAR rawio = TRUE;
+ WinUsb_SetPipePolicy(winusbHandle, outep, RAW_IO, sizeof(rawio), &rawio);
+ WinUsb_SetPipePolicy(winusbHandle, inep, RAW_IO, sizeof(rawio), &rawio);
+ //ULONG transize;
+ //ULONG transizelen = sizeof(transize);
+ //WinUsb_GetPipePolicy(winusbHandle, outep, MAXIMUM_TRANSFER_SIZE, &transizelen, &transize);
+ //transizelen = sizeof(transize);
+ //WinUsb_GetPipePolicy(winusbHandle, inep, MAXIMUM_TRANSFER_SIZE, &transizelen, &transize);
+ WINUSB_SETUP_PACKET setup = {0x41, 0x01, 0x0040, 0x0000, 0x0000};
+ ULONG transfered = 0;
+ if (!WinUsb_ControlTransfer(winusbHandle, setup, NULL, 0, &transfered, NULL)) {
+ printf("Fail to invoke WinUsb_ControlTransfer, last error %lu\n", GetLastError());
+ }
+ DWORD timeout = 1000;
+ WinUsb_SetPipePolicy(winusbHandle, outep, PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout);
+ WinUsb_SetPipePolicy(winusbHandle, inep, PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout);
+
+ this->deviceFile = deviceFile;
+ this->interfaceHandle = winusbHandle;
+ this->readPipe = inep; // 0x81
+ this->writePipe = outep; // 0x01
+ } else {
+ HANDLE deviceFile = CreateFileA(devicePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (deviceFile == INVALID_HANDLE_VALUE) {
+ return;
+ }
+ //char InBuffer[64];
+ //DWORD BytesReturned = 0;
+ //DeviceIoControl(deviceFile, 0x220468u, InBuffer, 0x40u, InBuffer, 0x40u, &BytesReturned, 0);
+ //quickdump(0, (unsigned char*)InBuffer, sizeof(InBuffer));
+ char pipeFileName[1024] = {0};
+ strcpy_s(pipeFileName, devicePath.c_str());
+ strcat_s(pipeFileName, "\\pipe00");
+ HANDLE readPipeFile = CreateFileA(pipeFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (readPipeFile == INVALID_HANDLE_VALUE) {
+ CloseHandle(deviceFile);
+ return;
+ }
+
+ strcpy_s(pipeFileName, devicePath.c_str());
+ strcat_s(pipeFileName, "\\pipe01");
+ HANDLE writePipeFile = CreateFileA(pipeFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (writePipeFile == INVALID_HANDLE_VALUE) {
+ CloseHandle(deviceFile);
+ CloseHandle(readPipeFile);
+ return;
+ }
+
+ this->deviceFile = deviceFile;
+ this->readPipeFile = readPipeFile;
+ this->writePipeFile = writePipeFile;
+ }
+ }
+}
+
+void JlinkDevice::close()
+{
+ if (deviceFile != INVALID_HANDLE_VALUE) {
+ if (isWinusb) {
+ WinUsb_Free(interfaceHandle);
+ } else {
+ CloseHandle(readPipeFile);
+ CloseHandle(writePipeFile);
+ }
+ CloseHandle(deviceFile);
+ deviceFile = INVALID_HANDLE_VALUE;
+ g_recvpos = 0;
+ }
+}
+
+void extractDevProp(const char* devpath, JlinkDevice &dev)
+{
+ char devid[MAX_DEVICE_ID_LEN];
+ extractDevID(devid, sizeof(devid), devpath);
+ DEVINST inst;
+ if (CM_Locate_DevNodeA(&inst, devid, 0) == CR_SUCCESS) {
+ char hubid[MAX_DEVICE_ID_LEN];
+ char hubname[MAX_DEVICE_ID_LEN];
+ int devport = -1;
+ if (lookupTopSeggerDevID(&inst, 0x1366, devid, hubid, hubname, &devport)) {
+ if (const char* vidstr = strchr(devid, '\\')) {
+ vidstr++;
+ uint32_t lvid, lpid;
+ if (sscanf_s(vidstr, "VID_%04x&PID_%04x", &lvid, &lpid) == 2) {
+ dev.pid = lpid;
+ dev.vid = lvid;
+ }
+ if (const char* snstr = strchr(vidstr, '\\')) {
+ snstr++;
+ dev.winSerial = atoi(snstr);
+ }
+ dev.locationInfo.hubDevID.assign(hubid);
+ dev.locationInfo.hubName.assign(hubname);
+ dev.locationInfo.devPort = devport;
+ }
+ }
+ }
+}
+
bool getWinUSBLinks(JLinkDevVec& vec, const GUID* guid)
{
- HDEVINFO devInfoSet = SetupDiGetClassDevsW(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ HDEVINFO devInfoSet = SetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
SP_DEVICE_INTERFACE_DATA interfaceData = {0};
interfaceData.cbSize = sizeof(interfaceData);
@@ -90,15 +242,15 @@ bool getWinUSBLinks(JLinkDevVec& vec, const GUID* guid)
}
DWORD requiredSize = 0;
- SetupDiGetDeviceInterfaceDetailW(devInfoSet, &interfaceData, NULL, 0, &requiredSize, NULL);
+ SetupDiGetDeviceInterfaceDetailA(devInfoSet, &interfaceData, NULL, 0, &requiredSize, NULL);
- PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiredSize);
- interfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
- if (!SetupDiGetDeviceInterfaceDetailW(devInfoSet, &interfaceData, interfaceDetailData, requiredSize, &requiredSize, NULL)) {
+ PSP_DEVICE_INTERFACE_DETAIL_DATA_A interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)malloc(requiredSize);
+ interfaceDetailData->cbSize = sizeof(*interfaceDetailData);
+ if (!SetupDiGetDeviceInterfaceDetailA(devInfoSet, &interfaceData, interfaceDetailData, requiredSize, &requiredSize, NULL)) {
free(interfaceDetailData);
continue;
}
- HANDLE deviceFile = CreateFileW(interfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
+ HANDLE deviceFile = CreateFileA(interfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
if (deviceFile == INVALID_HANDLE_VALUE) {
free(interfaceDetailData);
continue;
@@ -109,8 +261,8 @@ bool getWinUSBLinks(JLinkDevVec& vec, const GUID* guid)
printf("Failed to invoke WinUsb_Initialize, last error %lu\n", GetLastError());
CloseHandle(deviceFile);
free(interfaceDetailData);
- //continue;
- return false;
+ continue;
+ //return false;
}
uint8_t desc[0x200];
ULONG desclen = 0x200;
@@ -118,7 +270,8 @@ bool getWinUSBLinks(JLinkDevVec& vec, const GUID* guid)
printf("Failed to invoke WinUsb_GetDescriptor, last error %lu\n", GetLastError());
CloseHandle(deviceFile);
free(interfaceDetailData);
- return false;
+ continue;
+ //return false;
}
uint8_t inep = 0, outep = 0;
PUSB_CONFIGURATION_DESCRIPTOR confdesc = (PUSB_CONFIGURATION_DESCRIPTOR)desc;
@@ -161,36 +314,25 @@ bool getWinUSBLinks(JLinkDevVec& vec, const GUID* guid)
dev.interfaceHandle = winusbHandle;
dev.readPipe = inep; // 0x81
dev.writePipe = outep; // 0x01
- //"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x"
- //"\\?\usb#vid_1366&pid_1020#000260113630#{c78607e8-de76-458b-b7c1-5c14a6f3a1d2}"
- //"\\?\usb#vid_1366&pid_1024&mi_02#9&1a05735c&0&0002#{c78607e8-de76-458b-b7c1-5c14a6f3a1d2}"
- if (const wchar_t* vidstr = wcschr((const wchar_t*)interfaceDetailData->DevicePath, L'#')) {
- vidstr++;
- uint32_t lvid, lpid;
- if (swscanf_s(vidstr, L"vid_%04x&pid_%04x", &lvid, &lpid) == 2) {
- dev.pid = lpid;
- dev.vid = lvid;
- }
- if (const wchar_t* snstr = wcschr(vidstr, L'#')) {
- snstr++;
- dev.serial = wcstoul(snstr, NULL, 0);
- }
- }
+ // "\\?\usb#vid_1366&pid_1020#000260113630#{c78607e8-de76-458b-b7c1-5c14a6f3a1d2}" winusb2
+ // "\\?\usb#vid_1366&pid_1024&mi_02#9&1a05735c&0&0002#{c78607e8-de76-458b-b7c1-5c14a6f3a1d2}" composite
+ // "USB\VID_1366&PID_1024&MI_02\9&1A05735C&0&0002"
+ extractDevProp(interfaceDetailData->DevicePath, dev);
+
vec.push_back(dev);
free(interfaceDetailData);
}
return true;
}
-bool getSeggerJlinks(JLinkDevVec& vec)
+bool getSeggerJlinks(JLinkDevVec& vec, const GUID* guid)
{
- GUID classGuid = { 0x54654E76, 0xdcf7, 0x4a7f, {0x87, 0x8A, 0x4E, 0x8F, 0xCA, 0x0A, 0xCC, 0x9A} };
- HDEVINFO devInfoSet = SetupDiGetClassDevsW(&classGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ HDEVINFO devInfoSet = SetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
SP_DEVICE_INTERFACE_DATA interfaceData = {0};
interfaceData.cbSize = sizeof(interfaceData);
for (DWORD i = 0; ; i++) {
- if (!SetupDiEnumDeviceInterfaces(devInfoSet, NULL, &classGuid, i, &interfaceData)) {
+ if (!SetupDiEnumDeviceInterfaces(devInfoSet, NULL, guid, i, &interfaceData)) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) {
break;
} else {
@@ -199,35 +341,31 @@ bool getSeggerJlinks(JLinkDevVec& vec)
}
DWORD requiredSize = 0;
- SetupDiGetDeviceInterfaceDetailW(devInfoSet, &interfaceData, NULL, 0, &requiredSize, NULL);
- PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiredSize);
- interfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
- if (!SetupDiGetDeviceInterfaceDetailW(devInfoSet, &interfaceData, interfaceDetailData, requiredSize, &requiredSize, NULL)) {
+ SetupDiGetDeviceInterfaceDetailA(devInfoSet, &interfaceData, NULL, 0, &requiredSize, NULL);
+ PSP_DEVICE_INTERFACE_DETAIL_DATA_A interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)malloc(requiredSize);
+ interfaceDetailData->cbSize = sizeof(*interfaceDetailData);
+ if (!SetupDiGetDeviceInterfaceDetailA(devInfoSet, &interfaceData, interfaceDetailData, requiredSize, &requiredSize, NULL)) {
free(interfaceDetailData);
continue;
}
- HANDLE deviceFile = CreateFileW(interfaceDetailData->DevicePath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ HANDLE deviceFile = CreateFileA(interfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (deviceFile == INVALID_HANDLE_VALUE) {
free(interfaceDetailData);
continue;
}
- //char InBuffer[64];
- //DWORD BytesReturned = 0;
- //DeviceIoControl(deviceFile, 0x220468u, InBuffer, 0x40u, InBuffer, 0x40u, &BytesReturned, 0);
- //quickdump(0, (unsigned char*)InBuffer, sizeof(InBuffer));
- wchar_t pipeFileName[1024] = {0};
- wcscpy_s(pipeFileName, interfaceDetailData->DevicePath);
- wcscat_s(pipeFileName, L"\\pipe00");
- HANDLE readPipeFile = CreateFileW(pipeFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ char pipeFileName[1024] = {0};
+ strcpy_s(pipeFileName, interfaceDetailData->DevicePath);
+ strcat_s(pipeFileName, "\\pipe00");
+ HANDLE readPipeFile = CreateFileA(pipeFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (readPipeFile == INVALID_HANDLE_VALUE) {
CloseHandle(deviceFile);
free(interfaceDetailData);
continue;
}
- wcscpy_s(pipeFileName, interfaceDetailData->DevicePath);
- wcscat_s(pipeFileName, L"\\pipe01");
- HANDLE writePipeFile = CreateFileW(pipeFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ strcpy_s(pipeFileName, interfaceDetailData->DevicePath);
+ strcat_s(pipeFileName, "\\pipe01");
+ HANDLE writePipeFile = CreateFileA(pipeFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (writePipeFile == INVALID_HANDLE_VALUE) {
CloseHandle(deviceFile);
CloseHandle(readPipeFile);
@@ -240,21 +378,10 @@ bool getSeggerJlinks(JLinkDevVec& vec)
dev.deviceFile = deviceFile;
dev.readPipeFile = readPipeFile;
dev.writePipeFile = writePipeFile;
- // TODO: get usb port path
- //"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x"
- //0x00e5d95c "\\?\usb#vid_1366&pid_0101#000260113630#{54654e76-dcf7-4a7f-878a-4e8fca0acc9a}"
- if (const wchar_t* vidstr = wcschr((const wchar_t*)interfaceDetailData->DevicePath, L'#')) {
- vidstr++;
- uint32_t lvid, lpid;
- if (swscanf_s(vidstr, L"vid_%04x&pid_%04x", &lvid, &lpid) == 2) {
- dev.pid = lpid;
- dev.vid = lvid;
- }
- if (const wchar_t* snstr = wcschr(vidstr, L'#')) {
- snstr++;
- dev.serial = wcstoul(snstr, NULL, 0);
- }
- }
+ // DONE: get usb port path
+ // "\\?\usb#vid_1366&pid_0101#000260113630#{54654e76-dcf7-4a7f-878a-4e8fca0acc9a}" segger2
+ extractDevProp(interfaceDetailData->DevicePath, dev);
+
vec.push_back(dev);
free(interfaceDetailData);
}
@@ -263,34 +390,457 @@ bool getSeggerJlinks(JLinkDevVec& vec)
bool getJLinks(JLinkDevVec& vec)
{
- GUID classGuid1 = { 0xC78607E8, 0xDE76, 0x458B, {0xB7, 0xC1, 0x5C, 0x14, 0xA6, 0xF3, 0xA1, 0xD2} };
- getSeggerJlinks(vec);
- //size_t oldcnt = vec.size();
- getWinUSBLinks(vec, &classGuid1);
- //if (vec.size() == oldcnt) {
- // GUID classGuid2 = {0xA5DCBF10, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED};
- // getWinUSBLinks(vec, &classGuid2);
- //}
+ getSeggerJlinks(vec, &seggerguid2);
+ getWinUSBLinks(vec, &winusbguid2);
return vec.size() > 0;
}
-size_t g_recvpos = 0;
-
void freeJLinks(JLinkDevVec& vec)
{
- for (JLinkDevVec::const_iterator it = vec.begin(); it != vec.end(); it++) {
- if (it->isWinusb) {
- WinUsb_Free(it->interfaceHandle);
- } else {
- CloseHandle(it->readPipeFile);
- CloseHandle(it->writePipeFile);
- }
- CloseHandle(it->deviceFile);
+ for (JLinkDevVec::iterator it = vec.begin(); it != vec.end(); it++) {
+ it->close();
}
g_recvpos = 0;
vec.clear();
}
+LRESULT CALLBACK LinkKeeper::ListernerWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ PDEV_BROADCAST_DEVICEINTERFACE_A devif = (PDEV_BROADCAST_DEVICEINTERFACE_A)lParam;
+ switch (message) {
+ case WM_DEVICECHANGE:
+ //printf("Received device change!\n");
+ switch (wParam) {
+ case DBT_DEVICEARRIVAL:
+ printf("%s connected\n", devif->dbcc_name);
+ LinkKeeper::processDeviceNotification(devif->dbcc_name, &devif->dbcc_classguid, true);
+ break;
+ case DBT_DEVICEREMOVECOMPLETE:
+ printf("%s removed\n", devif->dbcc_name);
+ LinkKeeper::processDeviceNotification(devif->dbcc_name, &devif->dbcc_classguid, true);
+ break;
+ }
+ break;
+ default:
+ return DefWindowProcA(hWnd, message, wParam, lParam);
+ }
+ return 0;
+}
+
+DWORD WINAPI LinkKeeper::ListenerExecute(LPVOID arg) {
+ LinkKeeper* self = (LinkKeeper*)arg;
+ WNDCLASSA windowClass = {};
+ windowClass.lpfnWndProc = ListernerWndProc;
+ windowClass.lpszClassName = "ListenerWindow";
+ if (!RegisterClassA(&windowClass)) {
+ return 1;
+ }
+ HWND messageWindow = CreateWindowA(windowClass.lpszClassName, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
+ DEV_BROADCAST_DEVICEINTERFACE_A NotificationFilter;
+
+ ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
+ NotificationFilter.dbcc_size = sizeof(NotificationFilter);
+ NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+ NotificationFilter.dbcc_classguid = seggerguid2;
+ HDEVNOTIFY notify1 = RegisterDeviceNotificationA(messageWindow, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
+ NotificationFilter.dbcc_classguid = winusbguid2;
+ HDEVNOTIFY notify2 = RegisterDeviceNotificationA(messageWindow, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
+ MSG msg;
+ while (GetMessage(&msg, 0, 0, 0) > 0 && self->fKeeping) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ UnregisterDeviceNotification(notify1);
+ UnregisterDeviceNotification(notify2);
+ DestroyWindow(messageWindow);
+ return msg.wParam;
+}
+
+LinkKeeper* theKeeper = 0;
+GUID winusbguid2 = { 0xC78607E8, 0xDE76, 0x458B, {0xB7, 0xC1, 0x5C, 0x14, 0xA6, 0xF3, 0xA1, 0xD2} };
+GUID seggerguid2 = { 0x54654E76, 0xdcf7, 0x4a7f, {0x87, 0x8A, 0x4E, 0x8F, 0xCA, 0x0A, 0xCC, 0x9A} };
+
+void startupKeeper()
+{
+ theKeeper = new LinkKeeper();
+ theKeeper->createKeeperThread();
+ theKeeper->scanJLinks();
+}
+
+void shutdownKeeper()
+{
+ if (LinkKeeper* keeper = (LinkKeeper*)InterlockedExchange((LONG*)&theKeeper, 0)) {
+ keeper->closeKeeperThread();
+ keeper->freeJLinks();
+ delete keeper;
+ }
+}
+
+LinkKeeper::LinkKeeper():fKeeping(true), fWaitReconnect(false)
+{
+
+}
+
+void LinkKeeper::createKeeperThread()
+{
+ fKeeping = true;
+ fKeeperThread = ::CreateThread(NULL, 0, ListenerExecute, this, 0, NULL);
+}
+
+void LinkKeeper::closeKeeperThread()
+{
+ fKeeping = false;
+ WaitForSingleObject(fKeeperThread, 1000);
+}
+
+int LinkKeeper::scanJLinks()
+{
+ size_t oldsize = fDevices.size();
+ enumerateDevices(&seggerguid2, false);
+ enumerateDevices(&winusbguid2, true);
+ return fDevices.size() - oldsize;
+}
+
+void LinkKeeper::freeJLinks()
+{
+ for (JLinkDevMap::iterator it = fDevices.begin(); it != fDevices.end(); it++) {
+ it->second.close();
+ }
+ //g_recvpos = 0;
+ fDevices.clear();
+}
+
+bool LinkKeeper::enumerateDevices(const GUID* guid, bool isWinUSB)
+{
+ HDEVINFO devInfoSet = SetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ SP_DEVICE_INTERFACE_DATA interfaceData = {0};
+ interfaceData.cbSize = sizeof(interfaceData);
+
+ for (DWORD i = 0; ; i++) {
+ if (!SetupDiEnumDeviceInterfaces(devInfoSet, NULL, guid, i, &interfaceData)) {
+ if (GetLastError() == ERROR_NO_MORE_ITEMS) {
+ break;
+ } else {
+ continue;
+ }
+ }
+
+ DWORD requiredSize = 0;
+ SetupDiGetDeviceInterfaceDetailA(devInfoSet, &interfaceData, NULL, 0, &requiredSize, NULL);
+ PSP_DEVICE_INTERFACE_DETAIL_DATA_A interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)malloc(requiredSize);
+ interfaceDetailData->cbSize = sizeof(*interfaceDetailData);
+ if (!SetupDiGetDeviceInterfaceDetailA(devInfoSet, &interfaceData, interfaceDetailData, requiredSize, &requiredSize, NULL)) {
+ free(interfaceDetailData);
+ continue;
+ }
+
+ JlinkDevice dev;
+ dev.isWinusb = isWinUSB;
+ dev.devicePath = interfaceDetailData->DevicePath;
+ // "\\?\usb#vid_1366&pid_0101#000260113630#{54654e76-dcf7-4a7f-878a-4e8fca0acc9a}" segger2
+ // "\\?\usb#vid_1366&pid_1020#000260113630#{c78607e8-de76-458b-b7c1-5c14a6f3a1d2}" winusb2
+ // "\\?\usb#vid_1366&pid_1024&mi_02#9&1a05735c&0&0002#{c78607e8-de76-458b-b7c1-5c14a6f3a1d2}" composite
+ // "USB\VID_1366&PID_1024&MI_02\9&1A05735C&0&0002"
+ extractDevProp(interfaceDetailData->DevicePath, dev);
+ free(interfaceDetailData);
+ dev.deviceFile = INVALID_HANDLE_VALUE;
+ if (fDevices.find(dev.locationInfo) == fDevices.end()) {
+ fDevices.insert(std::make_pair(dev.locationInfo, dev));
+ }
+ }
+ return true;
+}
+
+JlinkDevice* LinkKeeper::getCurrDevice()
+{
+ if (fUsedDevice.hubDevID.empty()) {
+ errprintf("Some connection error occurred. No device selected.\n");
+ return 0;
+ }
+ JLinkDevMap::iterator it = fDevices.find(fUsedDevice);
+ if (it != fDevices.end()) {
+ it->second.open();
+ return &it->second;
+ } else {
+ errprintf("Selected device missing from USB port (%s)!\n", fUsedDevice.hubDevID.c_str());
+ return 0;
+ }
+}
+
+bool LinkKeeper::processDeviceNotification(const char* devpath, const GUID* guid, bool add)
+{
+ bool issegger2 = memcmp(guid, &seggerguid2, sizeof(seggerguid2)) == 0;
+ bool iswinusb2 = memcmp(guid, &winusbguid2, sizeof(winusbguid2)) == 0;
+ if (issegger2 || iswinusb2) {
+ JlinkDevice dev;
+ extractDevProp(devpath, dev);
+ if (add) {
+ dev.isWinusb = iswinusb2;
+ if (theKeeper->fDevices.find(dev.locationInfo) == theKeeper->fDevices.end()) {
+ theKeeper->fDevices.insert(std::make_pair(dev.locationInfo, dev));
+ if (theKeeper->fUsedDevice == dev.locationInfo && theKeeper->fWaitReconnect) {
+ theKeeper->fWaitReconnect = false;
+ }
+ }
+ } else {
+ if (theKeeper->fUsedDevice == dev.locationInfo && theKeeper->fWaitReconnect == false) {
+ theKeeper->fUsedDevice.clear();
+ }
+ JLinkDevMap::iterator it = theKeeper->fDevices.find(dev.locationInfo);
+ if (it != theKeeper->fDevices.end()) {
+ it->second.close();
+ theKeeper->fDevices.erase(dev.locationInfo);
+ }
+ }
+ }
+ return true;
+}
+
+int LinkKeeper::getJLinksSnap(JLinkInfoVec& vec)
+{
+ int cnt = 0;
+ for (JLinkDevMap::const_iterator it = theKeeper->fDevices.begin(); it != theKeeper->fDevices.end(); it++) {
+ vec.push_back(it->second);
+ cnt++;
+ }
+ return cnt;
+}
+
+bool LinkKeeper::selectDevice(const hublocation& location)
+{
+ if (theKeeper->fDevices.find(location) != theKeeper->fDevices.end()) {
+ theKeeper->fUsedDevice = location;
+ return true;
+ }
+ return false;
+}
+
+void LinkKeeper::prepareReconnect()
+{
+ theKeeper->fWaitReconnect = true;
+}
+
+bool LinkKeeper::waitReconnect(uint32_t timeout, uint32_t step)
+{
+ DWORD newtick = GetTickCount() + timeout;
+ while (GetTickCount() < newtick) {
+ if (theKeeper->fWaitReconnect == false) {
+ return true;
+ }
+ SleepEx(step, TRUE);
+ }
+ return !theKeeper->fWaitReconnect;
+}
+
+bool LinkKeeper::sendCommand(void const* commandBuffer, uint32_t commandLength, void* resultBuffer, uint32_t resultHeaderLength)
+{
+ JlinkDevice* dev = theKeeper->getCurrDevice();
+ if (dev) {
+ return jlinkSendCommand(dev, commandBuffer, commandLength, resultBuffer, resultHeaderLength);
+ }
+ return false;
+}
+
+bool LinkKeeper::continueReadResult(void* resultBuffer, uint32_t resultLength)
+{
+ JlinkDevice* dev = theKeeper->getCurrDevice();
+ if (dev) {
+ return jlinkContinueReadResult(dev, resultBuffer, resultLength);
+ }
+ return false;
+}
+
+bool LinkKeeper::commandReadFirmwareVersion(void* dataBuffer)
+{
+ JlinkDevice* dev = theKeeper->getCurrDevice();
+ if (dev) {
+ return jlinkCommandReadFirmwareVersion(dev, dataBuffer);
+ }
+ return false;
+}
+
+bool LinkKeeper::loopReadFirmwareVersion(void* dataBuffer)
+{
+ JlinkDevice* dev = theKeeper->getCurrDevice();
+ if (dev) {
+ return jlinkLoopReadFirmwareVersion(dev, dataBuffer);
+ }
+ return false;
+}
+
+bool LinkKeeper::commandReadEmulatorMemory(uint32_t address, uint32_t length, void* dataBuffer)
+{
+ JlinkDevice* dev = theKeeper->getCurrDevice();
+ if (dev) {
+ return jlinkCommandReadEmulatorMemory(dev, address, length, dataBuffer);
+ }
+ return false;
+}
+
+bool LinkKeeper::commandSetEmulateOption(uint32_t option, uint32_t val, uint32_t* status)
+{
+ JlinkDevice* dev = theKeeper->getCurrDevice();
+ if (dev) {
+ return jlinkCommandSetEmulateOption(dev, option, val, status);
+ }
+ return false;
+}
+
+bool LinkKeeper::commandSendUpdateFirmware(uint8_t* reply)
+{
+ JlinkDevice* dev = theKeeper->getCurrDevice();
+ if (dev) {
+ return jlinkCommandSendUpdateFirmware(dev, reply);
+ }
+ return false;
+}
+
+bool LinkKeeper::commandSendSelectInterface(uint8_t newif, uint32_t* oldif)
+{
+ JlinkDevice* dev = theKeeper->getCurrDevice();
+ if (dev) {
+ return jlinkCommandSendSelectInterface(dev, newif, oldif);
+ }
+ return false;
+}
+
+bool LinkKeeper::dumpFullFirmware(uint32_t addr, uint32_t size, void* buf)
+{
+ JlinkDevice* dev = theKeeper->getCurrDevice();
+ if (dev) {
+ return jlinkDumpFullFirmware(dev, addr, size, buf);
+ }
+ return false;
+}
+
+bool LinkKeeper::commandReadUID(uint32_t* size, void* dataBuffer)
+{
+ JlinkDevice* dev = theKeeper->getCurrDevice();
+ if (dev) {
+ return jlinkCommandReadUID(dev, size, dataBuffer);
+ }
+ return false;
+}
+
+bool LinkKeeper::commandReadOTS(void* dataBuffer)
+{
+ JlinkDevice* dev = theKeeper->getCurrDevice();
+ if (dev) {
+ return jlinkCommandReadOTS(dev, dataBuffer);
+ }
+ return false;
+}
+
+void extractDevID(char *devid, size_t len, const char *devpath){
+ while (char c = *devpath++) {
+ switch(c) {
+ case '\\':
+ case '?':
+ continue;
+ case '{':
+ if (*(devid - 1) == '\\') {
+ devid--;
+ }
+ len = 1;
+ break;
+ case '#':
+ if (--len) {
+ *devid++ = '\\';
+ }
+ break;
+ default:
+ if (--len) {
+ *devid++ = toupper(c);
+ }
+ }
+ if (len == 1) {
+ break;
+ }
+ }
+ *devid = 0;
+}
+
+/* f18a0e88-c30c-11d0-8815-00a0c906bed8 */
+GUID GUID_DEVINTERFACE_USB_HUB = { 0xf18a0e88, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8} };
+
+bool lookupTopSeggerDevID(DEVINST* devinst, uint16_t vid, char* devid, char* hubid, char* hubname, int* port) {
+ DEVINST parent;
+ char parentid[MAX_DEVICE_ID_LEN];
+ char vidstr[9];
+ sprintf_s(vidstr, sizeof(vidstr), "VID_%04X", vid);
+ while (CM_Get_Parent(&parent, *devinst, 0) == CR_SUCCESS) {
+ if (CM_Get_Device_IDA(parent, parentid, MAX_DEVICE_ID_LEN, 0) != CR_SUCCESS) {
+ return false;
+ }
+ if (strstr(parentid, vidstr) == 0) {
+ // 此时devinst是复合, parent是hub
+ if (hubid) {
+ strcpy_s(hubid, MAX_DEVICE_ID_LEN, parentid);
+ }
+ // rewind devid
+ ULONG datatype;
+ bool ok = CM_Get_Device_IDA(*devinst, devid, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS;
+ char buf[512];
+ ULONG buflen = sizeof(buf);
+ if (CM_Get_DevNode_Registry_PropertyA(parent, CM_DRP_DEVICEDESC, &datatype, buf, &buflen, 0) == CR_SUCCESS) {
+ strcpy_s(hubname, MAX_DEVICE_ID_LEN, buf);
+ }
+ // Detect connection port
+ buflen = sizeof(buf);
+ if (CM_Get_DevNode_Registry_PropertyA(*devinst, CM_DRP_LOCATION_INFORMATION, &datatype, buf, &buflen, 0) == CR_SUCCESS) {
+ // under WinXP, location info is friendly name "J-Link"
+ if (strncmp(buf, "Port_#", sizeof "Port_#" - 1) == 0) {
+ *port = atoi(&buf[6]);
+ return ok;
+ }
+ }
+ WCHAR keyname[512];
+ ULONG keynamelen = 512;
+ if (CM_Get_DevNode_Registry_PropertyW(*devinst, CM_DRP_DRIVER, &datatype, keyname, &keynamelen, 0) != CR_SUCCESS) {
+ *port = 0;
+ return ok;
+ }
+ // tricky WinXP support (from USBView)
+ // devid to devpath
+ if (CM_Get_Device_Interface_ListA((LPGUID)&GUID_DEVINTERFACE_USB_HUB, parentid, buf, 512, 0) == CR_SUCCESS) {
+ // TODO: cache lookup table
+ HANDLE hubhandle = CreateFileA(buf, GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
+ USB_NODE_INFORMATION hubinfo;
+ DWORD readed;
+ if (DeviceIoControl(hubhandle, IOCTL_USB_GET_NODE_INFORMATION, &hubinfo, sizeof(hubinfo), &hubinfo, sizeof(hubinfo), &readed, NULL)) {
+ for (int i = 0; i < hubinfo.u.HubInformation.HubDescriptor.bNumberOfPorts; i++) {
+ USB_NODE_CONNECTION_INFORMATION conninfo;
+ conninfo.ConnectionIndex = i + 1;
+ if (DeviceIoControl(hubhandle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION, &conninfo, sizeof(conninfo), &conninfo, sizeof(conninfo), &readed, NULL)) {
+ if (conninfo.ConnectionStatus == DeviceConnected) {
+ USB_NODE_CONNECTION_DRIVERKEY_NAME nodename;
+ nodename.ConnectionIndex = i + 1;
+ if (DeviceIoControl(hubhandle, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, &nodename, sizeof(nodename), &nodename, sizeof(nodename), &readed, NULL)) {
+ ULONG infosize = nodename.ActualLength;
+ USB_NODE_CONNECTION_DRIVERKEY_NAME* pnodename = (USB_NODE_CONNECTION_DRIVERKEY_NAME*)malloc(infosize);
+ pnodename->ConnectionIndex = i + 1;
+ if (DeviceIoControl(hubhandle, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, pnodename, infosize, pnodename, infosize, &readed, NULL)) {
+ if (wcsicmp(keyname, pnodename->DriverKeyName) == 0) {
+ *port = i + 1;
+ free(pnodename);
+ break;
+ }
+ }
+ free(pnodename);
+ }
+ }
+ }
+ }
+ }
+ CloseHandle(hubhandle);
+ }
+ return ok;
+ }
+ *devinst = parent; // 逐步将devinst替换为顶层复合设备
+ }
+ return true;
+}
+
unsigned char g_recvbuf[0x1000];
bool jlinkSendCommand(JlinkDevice* dev, void const* commandBuffer, uint32_t commandLength, void* resultBuffer, uint32_t resultHeaderLength)
diff --git a/EDUReViver/usbconn.h b/EDUReViver/usbconn.h
index 5d7c714..e356539 100644
--- a/EDUReViver/usbconn.h
+++ b/EDUReViver/usbconn.h
@@ -4,59 +4,45 @@
#define WIN32_LEAN_AND_MEAN
#include
#include
+#include
+#include