版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zoosenpin/article/details/80163543
1 Disable USBSer SN Check
Write a reg file(Disable_Ser_SN_CHK.reg), then add the following comment.
Windows Registry Editor Version5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\usbflags]
"GlobalDisableSerNumGen"=hex:01
2 Windows读写USBSer端口
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <setupapi.h>
#include "serial_port.h"
#pragma comment(lib,"Setupapi.lib")
#define CH340_VID "vid_1a86"
#define CH340_PID "pid_7523"
#define STM32_VID "vid_0483"
#define STM32_PID "pid_374b"
typedef struct sp_dev {
HANDLE handle;
char dev_path[128];
bool ov_io;
bool in_use;
sp_disconnect_callback disconnect_cb;
}sp_dev_t;
static GUID spCH340Guid = {0x4D36E978, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}};
static GUID spSTM32Guid = {0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}};
//static GUID spSTM32Guid = {0xDBCE1CD9, 0xA320, 0x4B51, {0xA3, 0x65, 0xA0, 0xC3, 0xF3, 0xC5, 0xFB, 0x29}};
static sp_dev_t sp_devs[10];
static int g_dev_count = 0;
static unsigned char dev_path[128];
static char dev_name[10];
static void to_lower(unsigned char *s)
{
unsigned char *tmp = s;
int i = 0;
for (i=0; i<strlen((const char*)s); i++) {
if ((*tmp >= 'A') && (*tmp <= 'Z')) {
*tmp += 32;
}
tmp++;
}
}
static bool sp_get_devices(int chip_id)
{
GUID *guid;
switch (chip_id) {
case CHIP_CH340:
guid = &spCH340Guid;
break;
case CHIP_STM32:
guid = &spSTM32Guid;
break;
default:
printf("SHOULD provide chip ID for your application!\n");
return false;
}
HDEVINFO hDevInfo = SetupDiGetClassDevs(guid,
NULL,
NULL,
(DIGCF_PRESENT | DIGCF_INTERFACEDEVICE));
if (!hDevInfo) {
return false;
}
SP_DEVICE_INTERFACE_DATA devInfoData;
devInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
int deviceNo = 0;
SetLastError(NO_ERROR);
PSP_INTERFACE_DEVICE_DETAIL_DATA devDetail;
while (GetLastError() != ERROR_NO_MORE_ITEMS) {
if (SetupDiEnumInterfaceDevice(hDevInfo,
0,
guid,
deviceNo,
&devInfoData)) {
ULONG requiredLength = 0;
SetupDiGetInterfaceDeviceDetail(hDevInfo,
&devInfoData,
NULL,
0,
&requiredLength,
NULL);
devDetail =
(SP_INTERFACE_DEVICE_DETAIL_DATA *)malloc(requiredLength);
devDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
if (!SetupDiGetInterfaceDeviceDetail(hDevInfo,
&devInfoData,
devDetail,
requiredLength,
NULL,
NULL)) {
SetupDiDestroyDeviceInfoList(hDevInfo);
free(devDetail);
return false;
} else {
strcpy((char *)dev_path, devDetail->DevicePath);
to_lower(dev_path);
if (strstr((const char*)dev_path, CH340_VID) ||
strstr((const char*)dev_path, STM32_VID)) {
strcpy(sp_devs[g_dev_count++].dev_path, devDetail->DevicePath);
}
}
}
deviceNo++;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
free(devDetail);
if (g_dev_count > 0) {
return true;
}
return false;
}
static bool sp_send_command(HANDLE handle, sp_cfg_t *cfg)
{
DCB dcb;
COMMTIMEOUTS TimeOuts;
SetupComm(handle,1024,1024);
TimeOuts.ReadIntervalTimeout = 1000;
TimeOuts.ReadTotalTimeoutConstant = 5000;
TimeOuts.ReadTotalTimeoutMultiplier = 500;
TimeOuts.WriteTotalTimeoutConstant = 2000;
TimeOuts.WriteTotalTimeoutMultiplier = 500;
SetCommTimeouts(handle, &TimeOuts);
GetCommState(handle, &dcb);
dcb.ByteSize = 8;
if (cfg->flow_control) {
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
} else {
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fOutxDsrFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fTXContinueOnXoff = FALSE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
}
if (cfg->parity) {
dcb.fParity = true;
} else {
dcb.fParity = false;
dcb.Parity = NOPARITY;
}
switch (cfg->stop_bits) {
case SP_STOP_BITS_1:
dcb.StopBits = ONESTOPBIT;
break;
case SP_STOP_BITS_1_5:
dcb.StopBits = ONE5STOPBITS;
break;
case SP_STOP_BITS_2:
dcb.StopBits = TWOSTOPBITS;
break;
default:
break;
}
switch (cfg->baud_rate) {
case SP_BR_9600:
dcb.BaudRate = CBR_9600;
break;
case SP_BR_19200:
dcb.BaudRate = CBR_19200;
break;
case SP_BR_38400:
dcb.BaudRate = CBR_38400;
break;
case SP_BR_57600:
dcb.BaudRate = CBR_57600;
break;
case SP_BR_115200:
dcb.BaudRate = CBR_115200;
break;
default:
break;
}
if (SetCommState(handle, &dcb)) {
return true;
}
return false;
}
int sp_dev_name_list_legacy(char **str)
{
HKEY hKey;
int dev_count = 0;
bool flag = false;
if (str == NULL) {
flag = true;
}
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"HARDWARE\\DEVICEMAP\\SERIALCOMM",
NULL,
KEY_ALL_ACCESS,
&hKey) == ERROR_SUCCESS) {
DWORD idx = 0, lenName = 100, dwType;
char valName[100];
memset(valName,'\0',sizeof(valName));
while (RegEnumValue(hKey,
idx++,
(LPSTR)valName,
&lenName,
NULL,
&dwType,
NULL,
NULL) != ERROR_NO_MORE_ITEMS) {
BYTE strCom[80];
memset(strCom,0,80);
DWORD type=REG_SZ, cbData=80;
if (RegQueryValueEx(hKey,
valName,
NULL,
&type,
strCom,
&cbData) == ERROR_SUCCESS) {
if (flag) {
dev_count++;
} else {
strcpy(str[dev_count++], (const char *)strCom);
}
}
memset(valName, 0, sizeof(valName));
lenName = 100;
}
}
return dev_count;
}
int sp_open_legacy(sp_cfg_t *cfg)
{
if (cfg->dev_name != NULL) {
sp_devs[0].handle = CreateFile(cfg->dev_name,
GENERIC_READ|GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
cfg->ov_io ? (FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED) : FILE_ATTRIBUTE_NORMAL,
0);
}
if (sp_devs[0].handle == INVALID_HANDLE_VALUE) {
return -1;
} else {
if (sp_send_command(sp_devs[0].handle, cfg)) {
printf("Succeed to send command to serial port!\n");
sp_devs[0].disconnect_cb = cfg->disconnect_cb;
sp_devs[0].ov_io = cfg->ov_io;
return 0;
}
CloseHandle(sp_devs[0].handle);
sp_devs[0].handle = INVALID_HANDLE_VALUE;
return -1;
}
}
int sp_dev_count(int chip_id)
{
g_dev_count = 0;
if (true == sp_get_devices(chip_id)) {
return g_dev_count;
} else {
return 0;
}
}
int sp_open(int dev_no, sp_cfg_t *cfg)
{
if (dev_no < 0) {
return -1;
}
if (strlen(sp_devs[dev_no].dev_path) <= 1 ) {
return -1;
}
printf("%s\n", sp_devs[dev_no].dev_path);
sp_devs[dev_no].handle = CreateFile(sp_devs[dev_no].dev_path,
GENERIC_READ|GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
cfg->ov_io ? (FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED) : FILE_ATTRIBUTE_NORMAL,
0);
if (sp_devs[dev_no].handle == INVALID_HANDLE_VALUE) {
return -1;
} else {
if (sp_send_command(sp_devs[dev_no].handle, cfg)) {
printf("Succeed to send command to serial port!\n");
sp_devs[dev_no].disconnect_cb = cfg->disconnect_cb;
sp_devs[dev_no].ov_io = cfg->ov_io;
return dev_no;
}
CloseHandle(sp_devs[dev_no].handle);
sp_devs[dev_no].handle = INVALID_HANDLE_VALUE;
return -1;
}
}
int sp_read(int handle, char *buf, int len)
{
int actual_read = 0;
OVERLAPPED ov;
int rc = 0;
if (handle < 0) {
return -1;
}
if (sp_devs[handle].handle == INVALID_HANDLE_VALUE) {
return -1;
}
memset(&ov, 0, sizeof(ov));
ov.hEvent = CreateEvent(NULL, FALSE, FALSE, "sp_r");
rc = ReadFile(sp_devs[handle].handle, buf, len, (DWORD *)&actual_read,
sp_devs[handle].ov_io ? &ov: NULL);
if (rc) {
return actual_read;
} else {
if (sp_devs[handle].ov_io &&
GetLastError() == ERROR_IO_PENDING){
WaitForSingleObject(ov.hEvent, INFINITE);
//printf("[sp_read]Request completed.\n");
rc = GetOverlappedResult(
sp_devs[handle].handle,
&ov,
(DWORD *)&actual_read,
TRUE);
return actual_read;
} else {
return -1;
}
}
}
int sp_write(int handle, char *buf, int len)
{
int actual_written = 0;
OVERLAPPED ov;
int rc = 0;
if (handle < 0) {
return -1;
}
if (sp_devs[handle].handle == INVALID_HANDLE_VALUE) {
return -1;
}
memset(&ov, 0, sizeof(ov));
ov.hEvent = CreateEvent(NULL, FALSE, FALSE, "sp_w");
rc = WriteFile(sp_devs[handle].handle, buf, len, (DWORD *)&actual_written,
sp_devs[handle].ov_io ? &ov : NULL);
if (rc) {
return actual_written;
} else {
if (sp_devs[handle].ov_io &&
GetLastError() == ERROR_IO_PENDING) {
WaitForSingleObject(ov.hEvent, INFINITE);
//printf("[sp_write]Request completed.\n");
rc = GetOverlappedResult(
sp_devs[handle].handle,
&ov,
(DWORD *)&actual_written,
TRUE);
return actual_written;
} else {
return -1;
}
}
}
int sp_close(int handle)
{
if (handle < 0) {
return -1;
}
if (sp_devs[handle].handle == INVALID_HANDLE_VALUE) {
return -1;
}
CloseHandle(sp_devs[handle].handle);
sp_devs[handle].handle = INVALID_HANDLE_VALUE;
return 0;
}
Write a reg file(Disable_Ser_SN_CHK.reg), then add the following comment.
Windows Registry Editor Version5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\usbflags]
"GlobalDisableSerNumGen"=hex:01
2 Windows读写USBSer端口
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <setupapi.h>
#include "serial_port.h"
#pragma comment(lib,"Setupapi.lib")
#define CH340_VID "vid_1a86"
#define CH340_PID "pid_7523"
#define STM32_VID "vid_0483"
#define STM32_PID "pid_374b"
typedef struct sp_dev {
HANDLE handle;
char dev_path[128];
bool ov_io;
bool in_use;
sp_disconnect_callback disconnect_cb;
}sp_dev_t;
static GUID spCH340Guid = {0x4D36E978, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}};
static GUID spSTM32Guid = {0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}};
//static GUID spSTM32Guid = {0xDBCE1CD9, 0xA320, 0x4B51, {0xA3, 0x65, 0xA0, 0xC3, 0xF3, 0xC5, 0xFB, 0x29}};
static sp_dev_t sp_devs[10];
static int g_dev_count = 0;
static unsigned char dev_path[128];
static char dev_name[10];
static void to_lower(unsigned char *s)
{
unsigned char *tmp = s;
int i = 0;
for (i=0; i<strlen((const char*)s); i++) {
if ((*tmp >= 'A') && (*tmp <= 'Z')) {
*tmp += 32;
}
tmp++;
}
}
static bool sp_get_devices(int chip_id)
{
GUID *guid;
switch (chip_id) {
case CHIP_CH340:
guid = &spCH340Guid;
break;
case CHIP_STM32:
guid = &spSTM32Guid;
break;
default:
printf("SHOULD provide chip ID for your application!\n");
return false;
}
HDEVINFO hDevInfo = SetupDiGetClassDevs(guid,
NULL,
NULL,
(DIGCF_PRESENT | DIGCF_INTERFACEDEVICE));
if (!hDevInfo) {
return false;
}
SP_DEVICE_INTERFACE_DATA devInfoData;
devInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
int deviceNo = 0;
SetLastError(NO_ERROR);
PSP_INTERFACE_DEVICE_DETAIL_DATA devDetail;
while (GetLastError() != ERROR_NO_MORE_ITEMS) {
if (SetupDiEnumInterfaceDevice(hDevInfo,
0,
guid,
deviceNo,
&devInfoData)) {
ULONG requiredLength = 0;
SetupDiGetInterfaceDeviceDetail(hDevInfo,
&devInfoData,
NULL,
0,
&requiredLength,
NULL);
devDetail =
(SP_INTERFACE_DEVICE_DETAIL_DATA *)malloc(requiredLength);
devDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
if (!SetupDiGetInterfaceDeviceDetail(hDevInfo,
&devInfoData,
devDetail,
requiredLength,
NULL,
NULL)) {
SetupDiDestroyDeviceInfoList(hDevInfo);
free(devDetail);
return false;
} else {
strcpy((char *)dev_path, devDetail->DevicePath);
to_lower(dev_path);
if (strstr((const char*)dev_path, CH340_VID) ||
strstr((const char*)dev_path, STM32_VID)) {
strcpy(sp_devs[g_dev_count++].dev_path, devDetail->DevicePath);
}
}
}
deviceNo++;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
free(devDetail);
if (g_dev_count > 0) {
return true;
}
return false;
}
static bool sp_send_command(HANDLE handle, sp_cfg_t *cfg)
{
DCB dcb;
COMMTIMEOUTS TimeOuts;
SetupComm(handle,1024,1024);
TimeOuts.ReadIntervalTimeout = 1000;
TimeOuts.ReadTotalTimeoutConstant = 5000;
TimeOuts.ReadTotalTimeoutMultiplier = 500;
TimeOuts.WriteTotalTimeoutConstant = 2000;
TimeOuts.WriteTotalTimeoutMultiplier = 500;
SetCommTimeouts(handle, &TimeOuts);
GetCommState(handle, &dcb);
dcb.ByteSize = 8;
if (cfg->flow_control) {
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
} else {
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fOutxDsrFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fTXContinueOnXoff = FALSE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
}
if (cfg->parity) {
dcb.fParity = true;
} else {
dcb.fParity = false;
dcb.Parity = NOPARITY;
}
switch (cfg->stop_bits) {
case SP_STOP_BITS_1:
dcb.StopBits = ONESTOPBIT;
break;
case SP_STOP_BITS_1_5:
dcb.StopBits = ONE5STOPBITS;
break;
case SP_STOP_BITS_2:
dcb.StopBits = TWOSTOPBITS;
break;
default:
break;
}
switch (cfg->baud_rate) {
case SP_BR_9600:
dcb.BaudRate = CBR_9600;
break;
case SP_BR_19200:
dcb.BaudRate = CBR_19200;
break;
case SP_BR_38400:
dcb.BaudRate = CBR_38400;
break;
case SP_BR_57600:
dcb.BaudRate = CBR_57600;
break;
case SP_BR_115200:
dcb.BaudRate = CBR_115200;
break;
default:
break;
}
if (SetCommState(handle, &dcb)) {
return true;
}
return false;
}
int sp_dev_name_list_legacy(char **str)
{
HKEY hKey;
int dev_count = 0;
bool flag = false;
if (str == NULL) {
flag = true;
}
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"HARDWARE\\DEVICEMAP\\SERIALCOMM",
NULL,
KEY_ALL_ACCESS,
&hKey) == ERROR_SUCCESS) {
DWORD idx = 0, lenName = 100, dwType;
char valName[100];
memset(valName,'\0',sizeof(valName));
while (RegEnumValue(hKey,
idx++,
(LPSTR)valName,
&lenName,
NULL,
&dwType,
NULL,
NULL) != ERROR_NO_MORE_ITEMS) {
BYTE strCom[80];
memset(strCom,0,80);
DWORD type=REG_SZ, cbData=80;
if (RegQueryValueEx(hKey,
valName,
NULL,
&type,
strCom,
&cbData) == ERROR_SUCCESS) {
if (flag) {
dev_count++;
} else {
strcpy(str[dev_count++], (const char *)strCom);
}
}
memset(valName, 0, sizeof(valName));
lenName = 100;
}
}
return dev_count;
}
int sp_open_legacy(sp_cfg_t *cfg)
{
if (cfg->dev_name != NULL) {
sp_devs[0].handle = CreateFile(cfg->dev_name,
GENERIC_READ|GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
cfg->ov_io ? (FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED) : FILE_ATTRIBUTE_NORMAL,
0);
}
if (sp_devs[0].handle == INVALID_HANDLE_VALUE) {
return -1;
} else {
if (sp_send_command(sp_devs[0].handle, cfg)) {
printf("Succeed to send command to serial port!\n");
sp_devs[0].disconnect_cb = cfg->disconnect_cb;
sp_devs[0].ov_io = cfg->ov_io;
return 0;
}
CloseHandle(sp_devs[0].handle);
sp_devs[0].handle = INVALID_HANDLE_VALUE;
return -1;
}
}
int sp_dev_count(int chip_id)
{
g_dev_count = 0;
if (true == sp_get_devices(chip_id)) {
return g_dev_count;
} else {
return 0;
}
}
int sp_open(int dev_no, sp_cfg_t *cfg)
{
if (dev_no < 0) {
return -1;
}
if (strlen(sp_devs[dev_no].dev_path) <= 1 ) {
return -1;
}
printf("%s\n", sp_devs[dev_no].dev_path);
sp_devs[dev_no].handle = CreateFile(sp_devs[dev_no].dev_path,
GENERIC_READ|GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
cfg->ov_io ? (FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED) : FILE_ATTRIBUTE_NORMAL,
0);
if (sp_devs[dev_no].handle == INVALID_HANDLE_VALUE) {
return -1;
} else {
if (sp_send_command(sp_devs[dev_no].handle, cfg)) {
printf("Succeed to send command to serial port!\n");
sp_devs[dev_no].disconnect_cb = cfg->disconnect_cb;
sp_devs[dev_no].ov_io = cfg->ov_io;
return dev_no;
}
CloseHandle(sp_devs[dev_no].handle);
sp_devs[dev_no].handle = INVALID_HANDLE_VALUE;
return -1;
}
}
int sp_read(int handle, char *buf, int len)
{
int actual_read = 0;
OVERLAPPED ov;
int rc = 0;
if (handle < 0) {
return -1;
}
if (sp_devs[handle].handle == INVALID_HANDLE_VALUE) {
return -1;
}
memset(&ov, 0, sizeof(ov));
ov.hEvent = CreateEvent(NULL, FALSE, FALSE, "sp_r");
rc = ReadFile(sp_devs[handle].handle, buf, len, (DWORD *)&actual_read,
sp_devs[handle].ov_io ? &ov: NULL);
if (rc) {
return actual_read;
} else {
if (sp_devs[handle].ov_io &&
GetLastError() == ERROR_IO_PENDING){
WaitForSingleObject(ov.hEvent, INFINITE);
//printf("[sp_read]Request completed.\n");
rc = GetOverlappedResult(
sp_devs[handle].handle,
&ov,
(DWORD *)&actual_read,
TRUE);
return actual_read;
} else {
return -1;
}
}
}
int sp_write(int handle, char *buf, int len)
{
int actual_written = 0;
OVERLAPPED ov;
int rc = 0;
if (handle < 0) {
return -1;
}
if (sp_devs[handle].handle == INVALID_HANDLE_VALUE) {
return -1;
}
memset(&ov, 0, sizeof(ov));
ov.hEvent = CreateEvent(NULL, FALSE, FALSE, "sp_w");
rc = WriteFile(sp_devs[handle].handle, buf, len, (DWORD *)&actual_written,
sp_devs[handle].ov_io ? &ov : NULL);
if (rc) {
return actual_written;
} else {
if (sp_devs[handle].ov_io &&
GetLastError() == ERROR_IO_PENDING) {
WaitForSingleObject(ov.hEvent, INFINITE);
//printf("[sp_write]Request completed.\n");
rc = GetOverlappedResult(
sp_devs[handle].handle,
&ov,
(DWORD *)&actual_written,
TRUE);
return actual_written;
} else {
return -1;
}
}
}
int sp_close(int handle)
{
if (handle < 0) {
return -1;
}
if (sp_devs[handle].handle == INVALID_HANDLE_VALUE) {
return -1;
}
CloseHandle(sp_devs[handle].handle);
sp_devs[handle].handle = INVALID_HANDLE_VALUE;
return 0;
}