USBSer How-to

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/zoosenpin/article/details/80163543
今日推荐