├── .gitignore ├── include ├── CH347DLL.H ├── CH347DLL_EN.H ├── io_ch347.h └── ch347_xvcd_api.h ├── CH347 ├── i386 │ └── CH347DLL.lib ├── amd64 │ └── CH347DLLA64.lib ├── arm64 │ └── CH347DLLA64.lib ├── CH347DLL.H └── CH347DLL_EN.H ├── lib └── windows │ ├── i386 │ └── CH347DLL.lib │ ├── amd64 │ └── CH347DLLA64.lib │ └── arm64 │ └── CH347DLLA64.lib ├── Release_GUI └── Windows │ ├── X64 │ ├── SDL3.dll │ ├── ch347_xvcd.exe │ └── ch347_xvcd_gui.exe │ └── X86 │ ├── SDL3.dll │ ├── ch347_xvcd.exe │ └── ch347_xvcd_gui.exe ├── CMakeLists.txt ├── README.md ├── .github └── workflows │ └── build.yml └── src ├── ch347_xvcd_api.c ├── io_ch347.c └── xvcd.c /.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | .idea/ 3 | .vscode/ -------------------------------------------------------------------------------- /include/CH347DLL.H: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/include/CH347DLL.H -------------------------------------------------------------------------------- /include/CH347DLL_EN.H: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/include/CH347DLL_EN.H -------------------------------------------------------------------------------- /CH347/i386/CH347DLL.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/CH347/i386/CH347DLL.lib -------------------------------------------------------------------------------- /CH347/amd64/CH347DLLA64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/CH347/amd64/CH347DLLA64.lib -------------------------------------------------------------------------------- /CH347/arm64/CH347DLLA64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/CH347/arm64/CH347DLLA64.lib -------------------------------------------------------------------------------- /lib/windows/i386/CH347DLL.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/lib/windows/i386/CH347DLL.lib -------------------------------------------------------------------------------- /Release_GUI/Windows/X64/SDL3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/Release_GUI/Windows/X64/SDL3.dll -------------------------------------------------------------------------------- /Release_GUI/Windows/X86/SDL3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/Release_GUI/Windows/X86/SDL3.dll -------------------------------------------------------------------------------- /lib/windows/amd64/CH347DLLA64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/lib/windows/amd64/CH347DLLA64.lib -------------------------------------------------------------------------------- /lib/windows/arm64/CH347DLLA64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/lib/windows/arm64/CH347DLLA64.lib -------------------------------------------------------------------------------- /Release_GUI/Windows/X64/ch347_xvcd.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/Release_GUI/Windows/X64/ch347_xvcd.exe -------------------------------------------------------------------------------- /Release_GUI/Windows/X86/ch347_xvcd.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/Release_GUI/Windows/X86/ch347_xvcd.exe -------------------------------------------------------------------------------- /Release_GUI/Windows/X64/ch347_xvcd_gui.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/Release_GUI/Windows/X64/ch347_xvcd_gui.exe -------------------------------------------------------------------------------- /Release_GUI/Windows/X86/ch347_xvcd_gui.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AIOT-CAT/xvcd-ch347/HEAD/Release_GUI/Windows/X86/ch347_xvcd_gui.exe -------------------------------------------------------------------------------- /include/io_ch347.h: -------------------------------------------------------------------------------- 1 | #ifndef _IO_CH347_H 2 | #define _IO_CH347_H 3 | 4 | #include "ch347_xvcd_api.h" 5 | 6 | /*JTAG state machine.*/ 7 | enum { 8 | test_logic_reset, 9 | run_test_idle, 10 | 11 | select_dr_scan, 12 | capture_dr, 13 | shift_dr, 14 | exit1_dr, 15 | pause_dr, 16 | exit2_dr, 17 | update_dr, 18 | 19 | select_ir_scan, 20 | capture_ir, 21 | shift_ir, 22 | exit1_ir, 23 | pause_ir, 24 | exit2_ir, 25 | update_ir, 26 | 27 | num_states 28 | }; 29 | 30 | int io_init(dev_ctx *ch347_ctx); 31 | int io_set_period(dev_ctx *ch347_ctx, unsigned long frequency); 32 | int io_scan(dev_ctx *ch347_ctx, const unsigned char* tms, const unsigned char* tdi, unsigned char* tdo, int len); 33 | void io_close(dev_ctx *ch347_ctx); 34 | 35 | int usb_xfer(dev_ctx *ch347_ctx, unsigned wlen, unsigned rlen, unsigned *ract, bool defer); 36 | 37 | 38 | #endif -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(xvcd_ch347 VERSION 1.2) 3 | 4 | set(CMAKE_C_STANDARD 99) 5 | 6 | include_directories(${PROJECT_SOURCE_DIR}/include) 7 | 8 | set(SOURCES 9 | src/ch347_xvcd_api.c 10 | src/io_ch347.c 11 | src/xvcd.c 12 | ) 13 | 14 | if(UNIX) 15 | set(TARGET_ARCH "Linux") 16 | find_library(NEED_LIBRARY libusb-1.0.so REQUIRED) 17 | link_directories(${NEED_LIBRARY}) 18 | set(C_FLAG "") 19 | elseif(WIN32) 20 | set(CH347_DIR ${CMAKE_SOURCE_DIR}/lib/windows) 21 | 22 | if(NOT CMAKE_GENERATOR_PLATFORM) 23 | set(CMAKE_GENERATOR_PLATFORM "x64") 24 | endif() 25 | 26 | if(CMAKE_GENERATOR_PLATFORM STREQUAL "arm64") 27 | set(TARGET_ARCH "arm64") 28 | set(NEED_LIBRARY ${CH347_DIR}/arm64/CH347DLLA64.lib) 29 | elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "x64") 30 | set(TARGET_ARCH "amd64") 31 | set(NEED_LIBRARY ${CH347_DIR}/amd64/CH347DLLA64.lib) 32 | elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "win32") 33 | set(TARGET_ARCH "i386") 34 | set(NEED_LIBRARY ${CH347_DIR}/i386/CH347DLL.lib) 35 | else() 36 | message(FATAL_ERROR "Unsupported platform: ${CMAKE_GENERATOR_PLATFORM}") 37 | endif() 38 | set(C_FLAG "ws2_32") 39 | endif() 40 | 41 | set(TARGET_NAME "xvcd_ch347_${TARGET_ARCH}") 42 | add_executable(${TARGET_NAME} ${SOURCES}) 43 | target_link_libraries(${TARGET_NAME} ${C_FLAG} ${NEED_LIBRARY}) 44 | 45 | 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xvcd-ch347 2 | 3 | CH347 Xilinx Virtual Cable 4 | 5 | xvcd_ch347 of XVC (Xilinx Virtual Cable) protocol based on xvcd (https://github.com/tmbinc/xvcd) 6 | 7 | ## Compile 8 | 9 | ### Windows 10 | 11 | First, ensure you have Git and either Visual Studio (requires a license for commercial use) or Build Tools for Visual Studio (free from Microsoft) installed. 12 | 13 | Open **Developer PowerShell for Visual Studio** and run the following commands: 14 | 15 | ```powershell 16 | git clone https://github.com/AIOT-CAT/xvcd-ch347.git 17 | New-Item -Path 'xvcd-ch347\build' -ItemType Directory 18 | Set-Location 'xvcd-ch347\build' 19 | cmake .. 20 | cmake --build . --config Release 21 | ``` 22 | 23 | To obtain `CH347DLLA64.DLL`, download it from: [https://www.wch.cn/downloads/CH341PAR\_ZIP.html](https://www.wch.cn/downloads/CH341PAR_ZIP.html). 24 | 25 | ### Linux 26 | 27 | First install dependences: 28 | 29 | ```bash 30 | sudo apt-get update 31 | sudo apt-get install libusb-1.0-0-dev 32 | # This installs libusb 0.0.1, no need to install unless you clear what you are doing. 33 | # sudo apt-get install libusb-dev 34 | sudo apt install build-essentials cmake 35 | ``` 36 | 37 | or you can install libusb manually from: https://github.com/libusb/libusb.git 38 | 39 | ```bash 40 | git clone https://github.com/AIOT-CAT/xvcd-ch347.git 41 | mkdir -p xvcd-ch347/build 42 | cd xvcd-ch347/build 43 | cmake .. 44 | make 45 | ``` 46 | 47 | ## FAQ 48 | 49 | 1. **About clock** 50 | 51 | Support : `KHZ(468.75)`, `KHZ(937.5)`, `MHZ(1.875)`, `MHZ(3.75)`, `MHZ(7.5)`, `MHZ(15)`, `MHZ(30)`, `MHZ(60)`. 52 | 53 | If you need to set a 10MHz clock, choose 15MHz or 7.5MHz, and modify the `DEFAULT_JTAG-SPEED` variable in `xvcd_win.c` to correspond to the clock, such as `150000000`. 54 | 55 | If you have a better way to accelerate the speed of this xvcd, please communicate with me for research, or if there are other integrated methods such as Vivado, we can also communicate together. If there are results, we can open them up again to serve more developers, **oidcatiot@163.com** 56 | 57 | 58 | 2. **TODO** 59 | 60 | Operation in remote server mode... 61 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build xvcd-ch347 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | build-linux: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout repository 12 | uses: actions/checkout@v4 13 | 14 | - name: Install dependencies 15 | run: | 16 | sudo apt-get update 17 | sudo apt-get install -y libusb-1.0-0-dev build-essential cmake 18 | 19 | - name: Configure CMake 20 | run: | 21 | mkdir -p build 22 | cd build 23 | cmake .. 24 | 25 | - name: Build 26 | run: | 27 | cd build 28 | make 29 | 30 | - name: Upload Artifacts 31 | uses: actions/upload-artifact@v4 32 | with: 33 | name: xvcd_ch347_linux_builds 34 | path: | 35 | build/xvcd_ch347_Linux 36 | 37 | build-windows: 38 | runs-on: windows-latest 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v4 42 | 43 | - name: Add MSBuild to PATH 44 | uses: microsoft/setup-msbuild@v2 45 | 46 | - name: Build x64 Release 47 | run: | 48 | cmake -B build_x64 -A x64 49 | cmake --build build_x64 --config Release 50 | 51 | - name: Build x86 Release 52 | run: | 53 | cmake -B build_win32 -A win32 54 | cmake --build build_win32 --config Release 55 | 56 | - name: Ensure required DLLs 57 | run: | 58 | Add-Type -Assembly System.IO.Compression.FileSystem 59 | 60 | # Download CH341PAR.ZIP into memory 61 | $response = Invoke-WebRequest -Uri "https://www.wch.cn/download/file?id=7" -UseBasicParsing 62 | $stream = New-Object System.IO.MemoryStream 63 | $stream.Write($response.Content, 0, $response.RawContentLength) 64 | $stream.Seek(0, 'Begin') | Out-Null 65 | 66 | # Open ZipArchive from memory 67 | $archive = [System.IO.Compression.ZipArchive]::new($stream, [System.IO.Compression.ZipArchiveMode]::Read) 68 | 69 | # Helper function to extract single file 70 | function Extract-File($entryName, $outputPath) { 71 | $entry = $archive.Entries | Where-Object { $_.FullName -ieq $entryName } 72 | $outputFile = Join-Path $outputPath $entry.Name 73 | if ($entry -eq $null) { 74 | Write-Error "Entry $entryName not found in archive" 75 | exit 1 76 | } 77 | [IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $outputFile) 78 | Write-Host "Extracted $entryName to $outputFile" 79 | } 80 | 81 | # Extract the two DLLs 82 | [System.Environment]::CurrentDirectory = (Get-Location).Path 83 | Extract-File "CH341PAR/CH347DLLA64.DLL" "build_x64/Release" 84 | Extract-File "CH341PAR/CH347DLL.DLL" "build_win32/Release" 85 | 86 | # Cleanup 87 | $archive.Dispose() 88 | $stream.Dispose() 89 | 90 | 91 | - name: Upload Artifacts 92 | uses: actions/upload-artifact@v4 93 | with: 94 | name: xvcd_ch347_windows_builds 95 | path: | 96 | build_x64/Release/xvcd_ch347_amd64.exe 97 | build_x64/Release/CH347DLLA64.DLL 98 | build_win32/Release/xvcd_ch347_i386.exe 99 | build_win32/Release/CH347DLL.DLL -------------------------------------------------------------------------------- /include/ch347_xvcd_api.h: -------------------------------------------------------------------------------- 1 | #ifndef _CH347_XVCD_API_H_ 2 | #define _CH347_XVCD_API_H_ 3 | 4 | #if defined(_WIN32) || defined(__CYGWIN__)|| defined(__CYGWIN32__) || defined(__CYGWIN64__) || defined(__MSYS__) 5 | #define PLATFORM_WINDOWS 1 6 | #define _CRT_SECURE_NO_WARNINGS 7 | #define _WINSOCK_DEPRECATED_NO_WARNINGS 8 | #include 9 | #include 10 | #include 11 | #include 12 | #pragma comment(lib, "Ws2_32.lib") 13 | #include "CH347DLL.H" 14 | #else 15 | #define PLATFORM_UNIX 1 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #endif 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #define CH347_EP_OUT 0x06u 35 | #define CH347_EP_IN 0x86u 36 | 37 | #define JTAGIO_STA_OUT_TDI (0x10) 38 | #define JTAGIO_STA_OUT_TMS (0x02) 39 | #define JTAGIO_STA_OUT_TCK (0x01) 40 | #define JTAGIO_STA_OUT_TRST (0x20) 41 | #define TDI_H JTAGIO_STA_OUT_TDI 42 | #define TDI_L 0 43 | #define TMS_H JTAGIO_STA_OUT_TMS 44 | #define TMS_L 0 45 | #define TCK_H JTAGIO_STA_OUT_TCK 46 | #define TCK_L 0 47 | #define TRST_H JTAGIO_STA_OUT_TRST 48 | #define TRST_L 0 49 | 50 | #define KHZ(n) ((n)*UINT64_C(1000)) 51 | #define MHZ(n) ((n)*UINT64_C(1000000)) 52 | #define GHZ(n) ((n)*UINT64_C(1000000000)) 53 | 54 | #define HW_TDO_BUF_SIZE 4096 55 | #define SF_PACKET_BUF_SIZE 51200 /* Command packet length */ 56 | #define UCMDPKT_DATA_MAX_BYTES_USBHS 507 /* The data length contained in each command packet during USB high-speed operation */ 57 | #define UCMDPKT_DATA_MAX_BITS_USBHS 248 /* bit mode transfer 248 byte */ 58 | #define USBC_PACKET_USBHS 512 /* Maximum data length per packet at USB high speed */ 59 | #define USBC_PACKET_USBHS_SINGLE 510 /* usb high speed max package length */ 60 | #define CH347_CMD_HEADER 3 /* Protocol header length */ 61 | #define CH347_CMD_HEADER 3 /* 协议包头长度 62 | Protocol transmission format: CMD (1 byte) + Length (2 bytes) + Data */ 63 | #define CH347_CMD_INFO_RD 0xCA /* Parameter acquisition, used to obtain firmware version, 64 | TAG interface related parameters, etc */ 65 | #define CH347_CMD_JTAG_INIT 0xD0 /* JTAG Interface Initialization Command */ 66 | #define CH347_CMD_JTAG_BIT_OP 0xD1 /* JTAG interface pin bit control command */ 67 | #define CH347_CMD_JTAG_BIT_OP_RD 0xD2 /* JTAG interface pin bit control and read commands */ 68 | #define CH347_CMD_JTAG_DATA_SHIFT 0xD3 /* JTAG interface data shift command */ 69 | #define CH347_CMD_JTAG_DATA_SHIFT_RD 0xD4 /* JTAG interface data shift and read command */ 70 | 71 | typedef struct ch347_dev_info { 72 | uint16_t usb_vid; 73 | uint16_t usb_pid; 74 | uint16_t usb_bcd; 75 | uint8_t usb_manu[256]; 76 | uint8_t usb_product[256]; 77 | uint8_t usb_serial[256]; 78 | #ifdef PLATFORM_WINDOWS 79 | uint32_t usb_index; 80 | #else 81 | libusb_device *dev_handle; 82 | libusb_device_handle *op_handle; 83 | #endif 84 | uint32_t count; 85 | }dev_ctx; 86 | 87 | typedef 88 | #ifdef PLATFORM_WINDOWS 89 | SOCKET 90 | #else 91 | int 92 | #endif 93 | socket_t; 94 | 95 | #define INVALID_SOCKET_VAL (socket_t)(~0) 96 | #define __SOCKET_ERROR (-1) 97 | 98 | #define CH347_VENDOR_ID 0x1a86 99 | #define CH347T_PRODUCT_ID 0x55DD 100 | #define CH347F_PRODUCT_ID 0x55DE 101 | 102 | 103 | int network_init(); 104 | void network_cleanup(); 105 | void close_socket(socket_t socket); 106 | int get_last_error(); 107 | int sread(socket_t fd, void *target, int len); 108 | int swrite(socket_t fd, void *target, int len); 109 | int ch347_open(dev_ctx *ch347_ctx); 110 | int ch347_close(dev_ctx *ch347_ctx); 111 | int ch347_jtag_init(dev_ctx *ch347_ctx, uint8_t clock); 112 | int ch347_write(dev_ctx *ch347_ctx, uint8_t *data, uint32_t *len); 113 | int ch347_read(dev_ctx *ch347_ctx, uint8_t *data, uint32_t *len); 114 | 115 | #endif //_CH347_XVCD_API_H_ -------------------------------------------------------------------------------- /src/ch347_xvcd_api.c: -------------------------------------------------------------------------------- 1 | #include "ch347_xvcd_api.h" 2 | 3 | /* socket 相关函数 */ 4 | int network_init() 5 | { 6 | #ifdef PLATFORM_WINDOWS 7 | WSADATA wsa; 8 | return WSAStartup(MAKEWORD(2, 2), &wsa); 9 | #else 10 | return 0; // UNIX无需初始化 11 | #endif 12 | } 13 | 14 | void network_cleanup() 15 | { 16 | #ifdef PLATFORM_WINDOWS 17 | WSACleanup(); 18 | #endif 19 | } 20 | 21 | void close_socket(socket_t socket) 22 | { 23 | #ifdef PLATFORM_WINDOWS 24 | closesocket(socket); 25 | #else 26 | close(socket); 27 | #endif 28 | } 29 | 30 | int get_last_error() 31 | { 32 | #ifdef PLATFORM_WINDOWS 33 | return WSAGetLastError(); 34 | #else 35 | return errno; 36 | #endif 37 | } 38 | 39 | int sread(socket_t fd, void *target, int len) 40 | { 41 | char *t = target; 42 | while (len) { 43 | int r = recv(fd, t, len, 0); 44 | if (r == __SOCKET_ERROR || r == 0) { 45 | int err = get_last_error(); 46 | printf("Recv failed with error: %d\n", err); 47 | if (r == 0) { 48 | puts("Seems like connection was gracefully closed. Exiting"); 49 | } 50 | return r; 51 | } 52 | t += r; 53 | len -= r; 54 | } 55 | return 1; 56 | } 57 | 58 | int swrite(socket_t fd, void *target, int len) 59 | { 60 | char *t = target; 61 | while (len) { 62 | int r = send(fd, t, len, 0); 63 | if (r == __SOCKET_ERROR || r == 0) { 64 | int err = get_last_error(); 65 | printf("Send failed with error: %d\n", err); 66 | if (r == 0) { 67 | puts("Seems like connection was gracefully closed. Exiting"); 68 | } 69 | return r; 70 | } 71 | t += r; 72 | len -= r; 73 | } 74 | return 1; 75 | } 76 | 77 | /* ch347操作相关函数 */ 78 | int ch347_open(dev_ctx *ch347_ctx) 79 | { 80 | int ret = 0; 81 | #if PLATFORM_WINDOWS 82 | if (CH347OpenDevice(ch347_ctx->usb_index) != INVALID_HANDLE_VALUE) { 83 | printf("Open CH347 Succes.\n"); 84 | } else { 85 | printf("Open CH347 fail.\n"); 86 | return -1; 87 | } 88 | 89 | CH347SetTimeout(ch347_ctx->usb_index, 1000, 1000); 90 | #else 91 | if (ch347_ctx->dev_handle == NULL) 92 | return -1; 93 | 94 | ret = libusb_init(NULL); 95 | if (ret < 0) { 96 | printf("libusb_init failed: %s\n", libusb_error_name(ret)); 97 | return ret; 98 | } 99 | 100 | ret = libusb_open(ch347_ctx->dev_handle, &ch347_ctx->op_handle); 101 | if (ret < 0) { 102 | printf("libusb_open failed: %s\n", libusb_error_name(ret)); 103 | return ret; 104 | } 105 | 106 | // claim interface x 107 | int interface_num = 4; 108 | ret = libusb_claim_interface(ch347_ctx->op_handle, interface_num); 109 | if (ret < 0) { 110 | printf("libusb_claim_interface failed: %s\n", libusb_error_name(ret)); 111 | return ret; 112 | } 113 | #endif 114 | return 0; 115 | } 116 | 117 | int ch347_close(dev_ctx *ch347_ctx) 118 | { 119 | #if PLATFORM_WINDOWS 120 | CH347CloseDevice(ch347_ctx->usb_index); 121 | #else 122 | libusb_close(ch347_ctx->op_handle); 123 | libusb_exit(NULL); 124 | #endif 125 | return 0; 126 | } 127 | 128 | int ch347_jtag_init(dev_ctx *ch347_ctx, uint8_t clock) 129 | { 130 | int ret = 0; 131 | #if PLATFORM_WINDOWS 132 | ret = CH347Jtag_INIT(ch347_ctx->usb_index, clock); 133 | if (!ret) { 134 | printf("CH347Jtag_INIT failed: %d\n", ret); 135 | return -1; 136 | } 137 | #else 138 | unsigned long int i = 0, j; 139 | bool retVal; 140 | uint8_t cmdBuf[32] = ""; 141 | cmdBuf[i++] = CH347_CMD_JTAG_INIT; 142 | cmdBuf[i++] = 6; 143 | cmdBuf[i++] = 0; 144 | 145 | cmdBuf[i++] = 0; 146 | cmdBuf[i++] = clock; 147 | 148 | for (j = 0; j < 4; j++) 149 | cmdBuf[i++] = TCK_L | TMS_H | TDI_L | TRST_H; 150 | 151 | uint32_t mLength = i; 152 | if (!ch347_write(ch347_ctx, cmdBuf, &mLength) || (mLength != i)) 153 | return -1; 154 | 155 | mLength = 4; 156 | memset(cmdBuf, 0, sizeof(cmdBuf)); 157 | 158 | if (!ch347_read(ch347_ctx, cmdBuf, &mLength) || (mLength != 4)) 159 | return -1; 160 | 161 | retVal = ((cmdBuf[0] == CH347_CMD_JTAG_INIT) && 162 | (cmdBuf[CH347_CMD_HEADER] == 0)); 163 | #endif 164 | return 0; 165 | } 166 | 167 | int ch347_write(dev_ctx *ch347_ctx, uint8_t *data, uint32_t *len) 168 | { 169 | int ret = 0; 170 | #if PLATFORM_WINDOWS 171 | ULONG length = *len; 172 | ret = CH347WriteData(ch347_ctx->usb_index, data, &length); 173 | if (!ret) { 174 | printf("CH347WriteData failed: %d\n", ret); 175 | return false; 176 | } 177 | *len = length; 178 | #else 179 | int tmp_length = 0; 180 | ret = libusb_bulk_transfer(ch347_ctx->op_handle, 181 | CH347_EP_OUT, 182 | (char *)data, 183 | *len, 184 | &tmp_length, 100); 185 | *len = tmp_length; 186 | 187 | if (ret < 0) { 188 | printf("libusb_bulk_transfer write failed: %d\n", ret); 189 | return false; 190 | } 191 | #endif 192 | return true; 193 | } 194 | 195 | int ch347_read(dev_ctx *ch347_ctx, uint8_t *data, uint32_t *len) 196 | { 197 | int ret = 0; 198 | #if PLATFORM_WINDOWS 199 | ULONG length = *len; 200 | ret = CH347ReadData(ch347_ctx->usb_index, data, &length); 201 | if (!ret) { 202 | printf("CH347ReadData failed: %d\n", ret); 203 | return false; 204 | } 205 | *len = length; 206 | #else 207 | int tmp_length = 0; 208 | int size = *len; 209 | ret = libusb_bulk_transfer(ch347_ctx->op_handle, 210 | CH347_EP_IN, 211 | (char *)data, 212 | size, 213 | &tmp_length, 100); 214 | 215 | *len = tmp_length; 216 | if (ret < 0) { 217 | printf("libusb_bulk_transfer read failed: %d\n", ret); 218 | } 219 | #endif 220 | return true; 221 | } -------------------------------------------------------------------------------- /src/io_ch347.c: -------------------------------------------------------------------------------- 1 | #include "io_ch347.h" 2 | 3 | #define SINGLEDATA 1 4 | #define PACKDATA 0 5 | #define MAX_BUFFER 512 6 | 7 | unsigned int iIndex = 0; 8 | 9 | uint8_t ibuf[MAX_BUFFER]; 10 | uint8_t _obuf[MAX_BUFFER]; 11 | uint8_t *obuf = _obuf; 12 | 13 | int get_obuf_length() 14 | { 15 | return MAX_BUFFER - (obuf - _obuf); 16 | } 17 | 18 | int get_buffer_size() 19 | { 20 | return get_obuf_length(); 21 | } 22 | 23 | bool isFull() 24 | { 25 | return get_obuf_length() == 0; 26 | } 27 | 28 | int flush(dev_ctx *ch347_ctx) 29 | { 30 | return usb_xfer(ch347_ctx, 0, 0, 0, false); 31 | } 32 | 33 | int io_init(dev_ctx *ch347_ctx) 34 | { 35 | int ret = 0; 36 | ret = ch347_open(ch347_ctx); 37 | if (ret < 0) { 38 | printf("Open CH347 fail.\n"); 39 | return -1; 40 | } 41 | 42 | ret = ch347_jtag_init(ch347_ctx, 4); 43 | if (ret < 0) { 44 | printf("CH347Jtag_INIT failed: %d\n", ret); 45 | return -1; 46 | } 47 | 48 | return 0; 49 | } 50 | 51 | int io_set_period(dev_ctx *ch347_ctx, unsigned long frequency) 52 | { 53 | int i = 0; 54 | int clockIndex = 0; 55 | int RetVal; 56 | int period; 57 | unsigned long clock_rate = frequency; 58 | int speed_clock[] = {KHZ(468.75), KHZ(937.5), MHZ(1.875), MHZ(3.75), MHZ(7.5), MHZ(15), MHZ(30), MHZ(60)}; 59 | // int speed_clock[] = {MHZ(1.875), MHZ(3.75), MHZ(7.5), MHZ(15), MHZ(30), MHZ(60)}; 60 | 61 | for (i = 0; i < sizeof(speed_clock) / sizeof(int); i++) { 62 | if (clock_rate <= speed_clock[i]) { 63 | clockIndex = i; 64 | break; 65 | } 66 | } 67 | if (clockIndex > 7 || clock_rate > MHZ(60)) { 68 | clockIndex = 7; 69 | } 70 | RetVal = ch347_jtag_init(ch347_ctx, clockIndex); 71 | if (RetVal == -1) { 72 | printf("CH347 Set Clock failed\n"); 73 | return -1; 74 | } 75 | printf("CH347 Set Clock : %d.\n", speed_clock[clockIndex]); 76 | period = MHZ(1000) / speed_clock[i]; 77 | if (period > 10) 78 | period = period - (period % 10); 79 | return period; 80 | } 81 | 82 | int writeTDI(dev_ctx *ch347_ctx, const uint8_t *tx, uint8_t *rx, uint32_t len, bool end) 83 | { 84 | if (len == 0) { 85 | return 0; 86 | } 87 | unsigned bytes = (len - (end ? 1 : 0)) / 8; 88 | unsigned bits = len - bytes * 8; 89 | uint8_t *rptr = rx; 90 | const uint8_t *tptr = tx; 91 | const uint8_t *txend = tx + bytes; 92 | uint8_t cmd = (rx != NULL) ? CH347_CMD_JTAG_DATA_SHIFT_RD : CH347_CMD_JTAG_DATA_SHIFT; 93 | while (tptr < txend) { 94 | if (get_obuf_length() < 4) { 95 | flush(ch347_ctx); 96 | if (!isFull() || obuf != _obuf) { 97 | printf("flush fail\n"); 98 | } 99 | } 100 | if (obuf != _obuf) 101 | printf("have data\n"); 102 | int avail = get_obuf_length() - 3; 103 | int chunk = (txend - tptr < avail) ? txend - tptr : avail; 104 | if (tx) { 105 | memcpy(&obuf[3], tptr, chunk); 106 | } else { 107 | memset(&obuf[3], 0, chunk); 108 | } 109 | tptr += chunk; 110 | // write header 111 | obuf[0] = cmd; 112 | obuf[1] = (chunk >> 0) & 0xff; 113 | obuf[2] = (chunk >> 8) & 0xff; 114 | unsigned actual_length = 0; 115 | int ret = usb_xfer(ch347_ctx, chunk + 3, (rx) ? chunk + 3 : 0, &actual_length, rx == 0 && get_obuf_length()); 116 | if (!rx) 117 | continue; 118 | if (ibuf[0] != CH347_CMD_JTAG_DATA_SHIFT_RD) { 119 | printf("ibuf[0] != CH347_CMD_JTAG_DATA_SHIFT_RD\n"); 120 | } 121 | unsigned size = ibuf[1] + ibuf[2] * 0x100; 122 | if (ibuf[0] != CH347_CMD_JTAG_DATA_SHIFT_RD || actual_length - 3 != size) { 123 | printf("writeTDI: invalid read data\n"); 124 | } 125 | memcpy(rptr, &ibuf[3], size); 126 | rptr += size; 127 | } 128 | unsigned actual_length; 129 | if (bits == 0) 130 | return EXIT_SUCCESS; 131 | cmd = (rx) ? CH347_CMD_JTAG_BIT_OP_RD : CH347_CMD_JTAG_BIT_OP; 132 | if (get_obuf_length() < (int)(4 + bits * 2)) { 133 | flush(ch347_ctx); 134 | } 135 | uint8_t *ptr = &obuf[3]; 136 | uint8_t x = 0; 137 | const uint8_t *bptr = tx + bytes; 138 | for (unsigned i = 0; i < bits; ++i) { 139 | uint8_t txb = (tx) ? bptr[i >> 3] : 0; 140 | uint8_t _tdi = (txb & (1 << (i & 7))) ? TDI_H : 0; 141 | x = _tdi; 142 | if (i == bits - 1) { 143 | x |= TMS_H; 144 | } 145 | *ptr++ = x; 146 | *ptr++ = x | TCK_H; 147 | } 148 | *ptr++ = x & ~TCK_H; 149 | unsigned wlen = ptr - obuf; 150 | obuf[0] = cmd; 151 | obuf[1] = wlen - 3; 152 | obuf[2] = (wlen - 3) >> 8; 153 | int ret = usb_xfer(ch347_ctx, wlen, (rx) ? (bits + 3) : 0, &actual_length, rx == NULL); 154 | 155 | if (ret < 0) { 156 | printf("writeTDI: usb bulk read failed\n"); 157 | } 158 | if (!rx) 159 | return EXIT_SUCCESS; 160 | 161 | unsigned size = ibuf[1] + ibuf[2] * 0x100; 162 | if (ibuf[0] != CH347_CMD_JTAG_BIT_OP_RD || actual_length - 3 != size) { 163 | printf("writeTDI: invalid read data\n"); 164 | } 165 | for (unsigned i = 0; i < size; ++i) { 166 | if (ibuf[3 + i] == 0x01) { 167 | *rptr |= (0x01 << i); 168 | } else { 169 | *rptr &= ~(0x01 << i); 170 | } 171 | } 172 | return EXIT_SUCCESS; 173 | } 174 | 175 | bool is_all_zero(const uint8_t *ptr, size_t size) 176 | { 177 | unsigned char *byte_ptr = (unsigned char *)ptr; 178 | 179 | for (size_t i = 0; i < size; i++) { 180 | if (byte_ptr[i] != 0) { 181 | return false; 182 | } 183 | } 184 | return true; 185 | } 186 | 187 | int io_scan(dev_ctx *ch347_ctx, const unsigned char *TMS, const unsigned char *TDI, unsigned char *TDO, int bits) 188 | { 189 | unsigned char v; 190 | unsigned char CmdBuffer[2 * 16384 + 512]; 191 | unsigned char buffer[2 * 16384 + 512]; 192 | unsigned char rbuffer[2 * 16384 + 512]; 193 | unsigned long i, length, DI, DII, RetVal; 194 | uint32_t BI, Txlen; 195 | 196 | int count = 0; 197 | int nb8 = 0; 198 | 199 | if (bits > sizeof(CmdBuffer) / 2) { 200 | fprintf(stderr, "FATAL: out of buffer space for %d bits\n", bits); 201 | return -1; 202 | } 203 | 204 | DI = DII = BI = 0; 205 | if (is_all_zero(TMS, (bits + 7) / 8)) { 206 | // set tck to low 207 | v = TCK_L | TMS_L | TDI_L; 208 | unsigned char settck[] = {0xD2, 0x01, 0x00, 0x00}; 209 | // should return D2 D0 00 210 | int len = 4; 211 | if (!ch347_write(ch347_ctx, settck, &len) || len != 4) { 212 | printf("%d : CH347WriteData failed.\n", __LINE__); 213 | return -1; 214 | } 215 | memset(settck, 0, sizeof(settck)); 216 | len = 10; 217 | if (!ch347_read(ch347_ctx, settck, &len)) { 218 | printf("%d : CH347ReadData failed.\n", __LINE__); 219 | return -1; 220 | } 221 | if (len < 3) { 222 | for (int times = 0;times < 3;times++) { 223 | len = 10; 224 | if (!ch347_read(ch347_ctx, settck, &len)) { 225 | printf("%d : CH347ReadData failed.\n", __LINE__); 226 | return -1; 227 | } 228 | } 229 | } 230 | return writeTDI(ch347_ctx, TDI, TDO, bits, false); 231 | } 232 | while (DI < bits) { 233 | if ((bits - DI) > UCMDPKT_DATA_MAX_BITS_USBHS) 234 | length = UCMDPKT_DATA_MAX_BITS_USBHS; 235 | else 236 | length = bits - DI; 237 | 238 | CmdBuffer[BI++] = CH347_CMD_JTAG_BIT_OP_RD; 239 | CmdBuffer[BI++] = (unsigned char)(((length * 2) >> 0) & 0xFF); 240 | CmdBuffer[BI++] = (unsigned char)(((length * 2) >> 8) & 0xFF); 241 | 242 | for (i = 0; i < length; ++i) { 243 | v = TCK_L | TMS_L | TDI_L; 244 | if (TMS[nb8 + (i / 8)] & (1 << (i & 7))) { 245 | v |= TMS_H; 246 | } 247 | if (TDI[nb8 + (i / 8)] & (1 << (i & 7))) { 248 | v |= TDI_H; 249 | } 250 | CmdBuffer[BI++] = v; 251 | CmdBuffer[BI++] = v | TCK_H; 252 | } 253 | CmdBuffer[BI++] = v & ~TCK_H; 254 | CmdBuffer[1] = BI - 3; 255 | CmdBuffer[2] = (BI - 3) >> 8; 256 | 257 | // 添加用于处理大包数据时组包操作参数 258 | RetVal = ch347_write(ch347_ctx, CmdBuffer, &BI); 259 | if (!RetVal) { 260 | printf("CH347 Write data failed.\n"); 261 | return -1; 262 | } 263 | 264 | Txlen = length + 3; 265 | RetVal = ch347_read(ch347_ctx, rbuffer, &Txlen); 266 | if (!RetVal) { 267 | printf("CH347 read data failed.\n"); 268 | return -1; 269 | } 270 | memcpy(&buffer[DI], &rbuffer[CH347_CMD_HEADER], Txlen); 271 | 272 | if (Txlen != (length + 3)) { 273 | RetVal = ch347_read(ch347_ctx, rbuffer, &BI); 274 | if (!RetVal) { 275 | printf("CH347 read data failed.\n"); 276 | return -1; 277 | } 278 | memcpy(&buffer[DI + Txlen], rbuffer, BI); 279 | } 280 | BI = 0; 281 | memset(CmdBuffer, 0, sizeof(CmdBuffer)); 282 | 283 | DI += length; 284 | nb8 += (length / 8); 285 | } 286 | memset(TDO, 0, (bits + 7) / 8); 287 | 288 | for (i = 0; i < bits; ++i) { 289 | if (buffer[i] & 0x01) { 290 | TDO[i / 8] |= 1 << (i & 7); 291 | } 292 | } 293 | 294 | return 0; 295 | } 296 | 297 | void io_close(dev_ctx *ch347_ctx) 298 | { 299 | ch347_close(ch347_ctx); 300 | } 301 | 302 | int usb_xfer(dev_ctx *ch347_ctx, unsigned wlen, unsigned rlen, unsigned *ract, bool defer) 303 | { 304 | uint32_t actual_length = 0; 305 | 306 | if (defer && !rlen && obuf - _obuf > (wlen + 12)) { 307 | obuf += wlen; 308 | return 0; 309 | } 310 | 311 | if (obuf - _obuf > MAX_BUFFER) { 312 | printf("buffer overflow\n"); 313 | } 314 | 315 | wlen += obuf - _obuf; 316 | if (wlen > MAX_BUFFER) { 317 | printf("buffer overflow\n"); 318 | } 319 | obuf = _obuf; 320 | 321 | if (wlen == 0) { 322 | return 0; 323 | } 324 | 325 | int r = 0; 326 | if (wlen) { 327 | actual_length = wlen; 328 | if (!ch347_write(ch347_ctx, obuf, &actual_length) || actual_length != wlen) { 329 | printf("write fail.\n"); 330 | return -1; 331 | } 332 | } 333 | obuf = _obuf; 334 | int rlen_total = 0; 335 | uint8_t *pibuf = ibuf; 336 | if (rlen) { 337 | while (rlen) { 338 | actual_length = rlen; 339 | if (!ch347_read(ch347_ctx, pibuf, &actual_length)) { 340 | printf("read fail.\n"); 341 | return -1; 342 | } 343 | rlen -= actual_length; 344 | pibuf += actual_length; 345 | rlen_total += actual_length; 346 | } 347 | *ract = rlen_total; 348 | } 349 | return 0; 350 | } 351 | -------------------------------------------------------------------------------- /src/xvcd.c: -------------------------------------------------------------------------------- 1 | // xilinx virtual cable demon for jlink jtag 2 | // use connection string in Impact and another 3 | // xilinx_xvc host=localhost:2542 disableversioncheck=true 4 | #include "io_ch347.h" 5 | 6 | // #pragma comment(lib, "Ws2_32.lib") 7 | #define VECTOR_IN_SZ 2048 8 | 9 | #define STRINGIFY(x) #x 10 | #define TOSTRING(x) STRINGIFY(x) 11 | 12 | int DEFAULT_JTAG_SPEED = 30000000; // 30 Mhz 13 | 14 | static int jtag_state; 15 | static int verbose = 0; 16 | 17 | /*Listen on default port 2542.*/ 18 | int iPort = 2542; 19 | static int vlevel = 1; 20 | unsigned long iIndex_ch347 = 0; 21 | unsigned char szAddress[32] = ""; 22 | unsigned char serialNumber[32] = ""; 23 | 24 | dev_ctx xvcd_dev[16]; 25 | 26 | static int jtag_step(int state, int tms) 27 | { 28 | static const int next_state[num_states][2] = 29 | { 30 | [test_logic_reset] = {run_test_idle, test_logic_reset}, 31 | [run_test_idle] = {run_test_idle, select_dr_scan}, 32 | 33 | [select_dr_scan] = {capture_dr, select_ir_scan}, 34 | [capture_dr] = {shift_dr, exit1_dr}, 35 | [shift_dr] = {shift_dr, exit1_dr}, 36 | [exit1_dr] = {pause_dr, update_dr}, 37 | [pause_dr] = {pause_dr, exit2_dr}, 38 | [exit2_dr] = {shift_dr, update_dr}, 39 | [update_dr] = {run_test_idle, select_dr_scan}, 40 | 41 | [select_ir_scan] = {capture_ir, test_logic_reset}, 42 | [capture_ir] = {shift_ir, exit1_ir}, 43 | [shift_ir] = {shift_ir, exit1_ir}, 44 | [exit1_ir] = {pause_ir, update_ir}, 45 | [pause_ir] = {pause_ir, exit2_ir}, 46 | [exit2_ir] = {shift_ir, update_ir}, 47 | [update_ir] = {run_test_idle, select_dr_scan}}; 48 | 49 | return next_state[state][tms]; 50 | } 51 | 52 | void printTDO(const unsigned char *buf, int bitLen) 53 | { 54 | printf(" TDO: "); 55 | for (int i = 0; i < bitLen; i += 8) { 56 | printf("%.2X", buf[(bitLen - i - 1) / 8]); 57 | } 58 | printf("\n"); 59 | } 60 | 61 | int getInt32(unsigned char *data) 62 | { 63 | // Return an int from the received byte string, data. data is 64 | // expected to be 4 bytes long. 65 | int num; 66 | 67 | // The int32 in data is sent little endian 68 | num = data[3]; 69 | num = (num << 8) | data[2]; 70 | num = (num << 8) | data[1]; 71 | num = (num << 8) | data[0]; 72 | 73 | return num; 74 | } 75 | 76 | void putInt32(unsigned char *data, int num) 77 | { 78 | // Convert the int32_t number, num, into a 4-byte, little endian 79 | // string pointed to by data 80 | data[0] = num & 0x00ff; 81 | num >>= 8; 82 | data[1] = num & 0x00ff; 83 | num >>= 8; 84 | data[2] = num & 0x00ff; 85 | num >>= 8; 86 | data[3] = num & 0x00ff; 87 | num >>= 8; 88 | } 89 | 90 | // 91 | // handle_data(fd) handles JTAG shift instructions. 92 | // To allow multiple programs to access the JTAG chain 93 | // at the same time, we only allow switching between 94 | // different clients only when we're in run_test_idle 95 | // after going test_logic_reset. This ensures that one 96 | // client can't disrupt the other client's IR or state. 97 | // 98 | int handle_data(dev_ctx *ch347_ctx, socket_t fd, unsigned long frequency) 99 | { 100 | int i; 101 | int seen_tlr = 0; 102 | int retVal = 0; 103 | const char xvcInfo[] = "xvcServer_v1.0:" TOSTRING(VECTOR_IN_SZ) "\n"; 104 | do { 105 | char cmd[16]; 106 | unsigned char buffer[2048], result[2048]; 107 | // unsigned char buffer[4096], result[4096]; 108 | 109 | if (sread(fd, cmd, 2) != 1) 110 | return 1; 111 | if (memcmp(cmd, "ge", 2) == 0) { // 获取信息 112 | if (sread(fd, cmd, 6) != 1) 113 | return 1; 114 | memcpy(result, xvcInfo, strlen(xvcInfo)); 115 | 116 | if (swrite(fd, result, strlen(xvcInfo)) != 1) { 117 | printf("[%d]write %d bytes != %ld\n", __LINE__, retVal, strlen(xvcInfo)); 118 | return 1; 119 | } 120 | if (vlevel > 0) { 121 | printf("%u : Received command: 'getinfo'\n", (int)time(NULL)); 122 | printf("\t Replied with %s\n", xvcInfo); 123 | } 124 | break; 125 | } else if (memcmp(cmd, "se", 2) == 0) { // 速度设置 126 | if (sread(fd, cmd, 9) != 1) 127 | return 1; 128 | 129 | // Convert the 4-byte little endian integer after "settck:" to be an integer 130 | int period, actPeriod; 131 | 132 | // if frequency argument is non-0, use it instead of the 133 | // period from the settck: command 134 | if (frequency == 0) { 135 | period = getInt32((unsigned char *)cmd + 5); 136 | } else { 137 | period = 1000000000 / frequency; 138 | } 139 | 140 | printf("Get the period:%d.\n", period); 141 | 142 | actPeriod = io_set_period(ch347_ctx, frequency); 143 | 144 | if (actPeriod < 0) { 145 | fprintf(stderr, "Error while setting the JTAG TCK period\n"); 146 | actPeriod = period; /* on error, simply echo back the period value so client while not try to change it*/ 147 | } 148 | 149 | putInt32(result, actPeriod); 150 | 151 | if (swrite(fd, result, 4) != 1) { 152 | return 1; 153 | } 154 | if (vlevel > 0) { 155 | printf("%u : Received command: 'settck'\n", (int)time(NULL)); 156 | printf("\t Replied with '%d'\n\n", actPeriod); 157 | } 158 | break; 159 | } else if (memcmp(cmd, "sh", 2) == 0) { 160 | if (sread(fd, cmd, 4) != 1) { 161 | return 1; 162 | } 163 | if (vlevel > 1) { 164 | printf("%u : Received command: 'shift'\n", (int)time(NULL)); 165 | } 166 | } else { 167 | fprintf(stderr, "invalid cmd '%s'\n", cmd); 168 | // return 1; 169 | } 170 | 171 | // 读取shift数据长度 172 | if (sread(fd, cmd + 6, 4) != 1) { 173 | fprintf(stderr, "reading length failed\n"); 174 | return 1; 175 | } 176 | 177 | int len; 178 | len = getInt32((unsigned char *)cmd + 6); 179 | 180 | int nr_bytes = (len + 7) / 8; 181 | if (nr_bytes * 2 > sizeof(buffer)) { 182 | fprintf(stderr, "buffer size exceeded\n"); 183 | return 1; 184 | } 185 | 186 | if (sread(fd, buffer, nr_bytes * 2) != 1) { 187 | fprintf(stderr, "reading data failed\n"); 188 | return 1; 189 | } 190 | memset(result, 0, sizeof(result)); 191 | 192 | if (vlevel > 2) { 193 | printf("\tNumber of Bits : %d\n", len); 194 | printf("\tNumber of Bytes : %d \n", nr_bytes); 195 | for (i = 0; i < nr_bytes; i++) 196 | printf("%02x ", buffer[i]); 197 | printf("\n"); 198 | } 199 | 200 | // Only allow exiting if the state is rti and the IR 201 | // has the default value (IDCODE) by going through test_logic_reset. 202 | // As soon as going through capture_dr or capture_ir no exit is 203 | // allowed as this will change DR/IR. 204 | seen_tlr = (seen_tlr || jtag_state == test_logic_reset) && (jtag_state != capture_dr) && (jtag_state != capture_ir); 205 | 206 | // Due to a weird bug(??) xilinx impacts goes through another "capture_ir"/"capture_dr" cycle after 207 | // reading IR/DR which unfortunately sets IR to the read-out IR value. 208 | // Just ignore these transactions. 209 | if ((jtag_state == exit1_ir && len == 5 && buffer[0] == 0x17) || 210 | (jtag_state == exit1_dr && len == 4 && buffer[0] == 0x0b)) { 211 | if (verbose) 212 | printf("ignoring bogus jtag state movement in jtag_state %d\n", jtag_state); 213 | } else { 214 | for (i = 0; i < len; ++i) { 215 | // Do the actual cycle. 216 | int tms = !!(buffer[i / 8] & (1 << (i & 7))); 217 | 218 | // Track the state. 219 | jtag_state = jtag_step(jtag_state, tms); 220 | } 221 | 222 | if (io_scan(ch347_ctx, buffer, buffer + nr_bytes, result, len) < 0) { 223 | fprintf(stderr, "io_scan failed\n"); 224 | exit(1); 225 | } 226 | 227 | if (verbose) { 228 | for (i = 0; i < nr_bytes; ++i) 229 | printf("%02x ", result[i]); 230 | } 231 | } 232 | 233 | if (send(fd, (const char *)result, nr_bytes, 0) != nr_bytes) { 234 | printf("Send failed with error: %d\n", get_last_error()); 235 | return 1; 236 | } 237 | 238 | if (verbose) { 239 | printf("jtag state %d\n", jtag_state); 240 | } 241 | } while (!(seen_tlr && jtag_state == run_test_idle)); 242 | if (verbose) { 243 | puts("exit handle_data"); 244 | } 245 | return 0; 246 | } 247 | 248 | void usage(void) 249 | { 250 | const char use[] = 251 | " Usage:\n" 252 | " -h, --help display this message\n" 253 | " -a, --address specify host address, default is 127.0.0.1\n" 254 | " -p, --port specify socket port, default is 2542\n" 255 | " -i, --index specify CH347 index, default is 0\n" 256 | " -s, --speed specify CH347 JTAG speed, default is 30MHz\n" 257 | " -S, --serialnumber Specify the CH347 serial number to open\n" 258 | "\n\n"; 259 | printf(use); 260 | ; 261 | exit(0); 262 | } 263 | 264 | int main(int argc, char **argv) 265 | { 266 | int ret = 0; 267 | int i, c, iResult; 268 | socket_t s; 269 | struct sockaddr_in address; 270 | unsigned short port = iPort; 271 | unsigned short jtagSpeed = DEFAULT_JTAG_SPEED; 272 | unsigned int coreId = 0; 273 | for (int i = 1; i < argc; ++i) { 274 | if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { 275 | usage(); 276 | } else if (!strcmp(argv[i], "-a") || !strcmp(argv[i], "--address") && i + 1 < argc) { 277 | strcpy(szAddress, argv[i + 1]); 278 | ++i; 279 | } else if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "--port") && i + 1 < argc) { 280 | iPort = atoi(argv[i + 1]); 281 | printf("port: %d\n", iPort); 282 | ++i; 283 | } else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--index") && i + 1 < argc) { 284 | iIndex_ch347 = atoi(argv[i + 1]); 285 | ++i; 286 | } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--speed") && i + 1 < argc) { 287 | DEFAULT_JTAG_SPEED = atoi(argv[i + 1]); 288 | ++i; 289 | } else if (!strcmp(argv[i], "-S") || !strcmp(argv[i], "--serialnum") && i + 1 < argc) { 290 | strcpy(serialNumber, argv[i + 1]); 291 | ++i; 292 | } else { 293 | usage(); 294 | } 295 | } 296 | #if PLATFORM_WINDOWS 297 | xvcd_dev[iIndex_ch347].usb_index = iIndex_ch347; 298 | #else 299 | libusb_context *ctx = NULL; 300 | libusb_device **devs; 301 | libusb_device_handle *dev_handle = NULL; 302 | uint8_t serial_idx; // 序列号索引 303 | uint8_t product_idx; // 产品描述符索引 304 | uint8_t manu_idx; // 厂商描述符索引 305 | uint8_t dev_index = 0; 306 | uint8_t *NA = "N/A"; 307 | uint32_t r = 0; 308 | 309 | ret = libusb_init(&ctx); // 初始化上下文 310 | if (ret != LIBUSB_SUCCESS) { 311 | fprintf(stderr, "初始化失败: %s\n", libusb_error_name(ret)); 312 | return -1; 313 | } 314 | 315 | ssize_t cnt = libusb_get_device_list(ctx, &devs); // 获取设备列表 316 | if (cnt < 0) { 317 | fprintf(stderr, "设备枚举失败\n"); 318 | libusb_exit(ctx); 319 | return -1; 320 | } 321 | 322 | // 遍历设备,按VID/PID筛选目标设备 323 | for (int i = 0; i < cnt; i++) { 324 | libusb_device *dev = devs[i]; 325 | struct libusb_device_descriptor desc; 326 | libusb_get_device_descriptor(dev, &desc); 327 | if (desc.idVendor == CH347_VENDOR_ID && (desc.idProduct == CH347T_PRODUCT_ID || desc.idProduct == CH347F_PRODUCT_ID)) { 328 | serial_idx = desc.iSerialNumber; 329 | product_idx = desc.iProduct; 330 | manu_idx = desc.iManufacturer; 331 | xvcd_dev[dev_index].dev_handle = dev; 332 | r = libusb_open(xvcd_dev[dev_index].dev_handle, &dev_handle); 333 | if (r < 0) { 334 | fprintf(stderr, "打开设备失败: %s\n", libusb_error_name(r)); 335 | libusb_free_device_list(devs, 1); // 释放设备列表 336 | libusb_exit(ctx); // 退出libusb 337 | break; 338 | } 339 | printf("Current index: %d\n", dev_index); 340 | r = libusb_get_string_descriptor_ascii(dev_handle, manu_idx, (unsigned char *)xvcd_dev[dev_index].usb_manu, sizeof(xvcd_dev[dev_index].usb_manu)); 341 | printf("厂商: %s\n", r > 0 ? xvcd_dev[dev_index].usb_manu : NA); 342 | r = libusb_get_string_descriptor_ascii(dev_handle, product_idx, (unsigned char *)xvcd_dev[dev_index].usb_product, sizeof(xvcd_dev[dev_index].usb_product)); 343 | printf("产品: %s\n", r > 0 ? xvcd_dev[dev_index].usb_product : NA); 344 | r = libusb_get_string_descriptor_ascii(dev_handle, serial_idx, (unsigned char *)xvcd_dev[dev_index].usb_serial, sizeof(xvcd_dev[dev_index].usb_serial)); 345 | printf("序列号: %s\n", r > 0 ? xvcd_dev[dev_index].usb_serial : NA); 346 | 347 | xvcd_dev[dev_index].usb_vid = desc.idVendor; 348 | xvcd_dev[dev_index].usb_pid = desc.idProduct; 349 | xvcd_dev[dev_index].usb_bcd = desc.bcdDevice; 350 | 351 | if (!strcmp(serialNumber, xvcd_dev[dev_index].usb_serial)) { 352 | iIndex_ch347 = dev_index; 353 | } 354 | 355 | dev_index++; 356 | xvcd_dev[dev_index].count = dev_index; 357 | libusb_close(dev_handle); // 关闭设备 358 | } 359 | } 360 | #endif 361 | 362 | if (io_init(&xvcd_dev[iIndex_ch347])) { 363 | fprintf(stderr, "io_init failed\n"); 364 | return 1; 365 | } 366 | 367 | iResult = network_init(); 368 | if (iResult != 0) { 369 | printf("WSAStartup failed: %d\n", iResult); 370 | return 1; 371 | } 372 | 373 | s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); 374 | 375 | if (s == INVALID_SOCKET_VAL) { 376 | printf("Error at socket(): %d\n", get_last_error()); 377 | network_cleanup(); 378 | return 1; 379 | } 380 | 381 | i = 1; 382 | setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof i); 383 | 384 | memset(&address, 0, sizeof(address)); 385 | address.sin_addr.s_addr = strcmp(szAddress, "") ? inet_addr(szAddress) : INADDR_ANY; 386 | address.sin_port = htons(iPort); 387 | address.sin_family = AF_INET; 388 | 389 | iResult = bind(s, (struct sockaddr *)&address, sizeof(address)); 390 | if (iResult == __SOCKET_ERROR) { 391 | printf("Bind failed with error: %d\n", get_last_error()); 392 | close_socket(s); 393 | network_cleanup(); 394 | return 1; 395 | } 396 | 397 | if (listen(s, 1024) == __SOCKET_ERROR) { 398 | printf("Listen failed with error: %d\n", get_last_error()); 399 | close_socket(s); 400 | network_cleanup(); 401 | return 1; 402 | } 403 | 404 | fd_set conn; 405 | int maxfd = 0; 406 | 407 | FD_ZERO(&conn); 408 | FD_SET(s, &conn); 409 | 410 | maxfd = s; 411 | if (verbose) { 412 | puts("Started"); 413 | } 414 | 415 | while (1) { 416 | fd_set read = conn, except = conn; 417 | socket_t fd; 418 | // Look for work to do. 419 | if (select(maxfd + 1, &read, 0, &except, 0) == __SOCKET_ERROR) { 420 | printf("Select failed with error: %d\n", get_last_error()); 421 | break; 422 | } 423 | 424 | for (fd = 0; fd <= maxfd; ++fd) { 425 | if (FD_ISSET(fd, &read)) { 426 | // Readable listen socket? Accept connection. 427 | if (fd == s) { 428 | socket_t newfd; 429 | int nsize = sizeof(address); 430 | 431 | newfd = accept(s, (struct sockaddr *)&address, &nsize); 432 | if (verbose) { 433 | printf("connection accepted - fd %d\n", newfd); 434 | } 435 | if (newfd == INVALID_SOCKET_VAL) { 436 | printf("accept failed with error: %d\n", get_last_error()); 437 | } else { 438 | puts("setting TCP_NODELAY to 1"); 439 | int flag = 1; 440 | int optResult = setsockopt(newfd, 441 | IPPROTO_TCP, 442 | TCP_NODELAY, 443 | (char *)&flag, 444 | sizeof(flag)); 445 | if (optResult < 0) { 446 | perror("TCP_NODELAY error"); 447 | } 448 | if (newfd > maxfd) { 449 | maxfd = newfd; 450 | } 451 | FD_SET(newfd, &conn); 452 | } 453 | } 454 | // Otherwise, do work. 455 | else { 456 | int r; 457 | if (verbose) { 458 | puts("start handle_data"); 459 | } 460 | r = handle_data(&xvcd_dev[iIndex_ch347], fd, DEFAULT_JTAG_SPEED); 461 | if (verbose) { 462 | puts("stop handle_data"); 463 | } 464 | if (r) { 465 | // Close connection when required. 466 | if (verbose) 467 | printf("connection closed - fd %d\n", fd); 468 | close_socket(fd); 469 | FD_CLR(fd, &conn); 470 | } 471 | } 472 | } 473 | // Abort connection? 474 | else if (FD_ISSET(fd, &except)) { 475 | if (verbose) { 476 | printf("connection aborted - fd %d\n", fd); 477 | } 478 | close_socket(fd); 479 | FD_CLR(fd, &conn); 480 | if (fd == s) 481 | break; 482 | } 483 | } 484 | } 485 | 486 | close_socket(s); 487 | network_cleanup(); 488 | // Un-map IOs. 489 | io_close(&xvcd_dev[iIndex_ch347]); 490 | 491 | return 0; 492 | } 493 | -------------------------------------------------------------------------------- /CH347/CH347DLL.H: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | ** Copyright (C) WCH 2001-2025 ** 3 | ** Web: http://wch.cn ** 4 | ******************************************************************************/ 5 | // USB���߽ӿ�оƬCH341/7����Ӧ�ò�ӿڿ�,CH347/9����480Mbps����USB������չUART/SPI/I2C/JTAG/SWD 6 | // CH346����480Mbps����USB������չUART/SPI SLAVE,UART/PARALLEL SLAVE 7 | // CH347-DLL V1.4 8 | // ���л���: Windows 98/ME, Windows 2000/XP, WIN7/8/10/11,and later. 9 | // support USB chip: CH341, CH341A,CH347,CH339W 10 | // USB => Parallel, I2C, SPI, JTAG, SWD, PARALLEL,UART ... 11 | //Notes: 12 | //Copyright (C) 2025 Nanjing Qinheng Microelectronics Co., Ltd. 13 | 14 | 15 | 16 | #ifndef _CH347_DLL_H 17 | #define _CH347_DLL_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #ifdef _WIN64 24 | #define mOFFSET( s, m ) ( (ULONG_PTR) & ( ( ( s * ) 0 ) -> m ) ) // �����ȡ�ṹ��Ա���ƫ�Ƶ�ַ�ĺ� 25 | #else 26 | #define mOFFSET( s, m ) ( (ULONG) & ( ( ( s * ) 0 ) -> m ) ) // �����ȡ�ṹ��Ա���ƫ�Ƶ�ַ�ĺ� 27 | #endif 28 | 29 | #ifndef max 30 | #define max( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) // �ϴ�ֵ 31 | #endif 32 | 33 | #ifndef min 34 | #define min( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) // ��Сֵ 35 | #endif 36 | 37 | #ifdef ExAllocatePool 38 | #undef ExAllocatePool // ɾ����TAG���ڴ���� 39 | #endif 40 | 41 | #ifndef NTSTATUS 42 | typedef LONG NTSTATUS; // ����״̬ 43 | #endif 44 | 45 | //��CH31DLL����CH341WDM���� 46 | #ifndef _CH341_DLL_H 47 | typedef struct _USB_SETUP_PKT { // USB���ƴ���Ľ����׶ε�����������ṹ 48 | UCHAR mUspReqType; // 00H �������� 49 | UCHAR mUspRequest; // 01H ������� 50 | union { 51 | struct { 52 | UCHAR mUspValueLow; // 02H ֵ�������ֽ� 53 | UCHAR mUspValueHigh; // 03H ֵ�������ֽ� 54 | }; 55 | USHORT mUspValue; // 02H-03H ֵ���� 56 | }; 57 | union { 58 | struct { 59 | UCHAR mUspIndexLow; // 04H �����������ֽ� 60 | UCHAR mUspIndexHigh; // 05H �����������ֽ� 61 | }; 62 | USHORT mUspIndex; // 04H-05H �������� 63 | }; 64 | USHORT mLength; // 06H-07H ���ݽ׶ε����ݳ��� 65 | } mUSB_SETUP_PKT, *mPUSB_SETUP_PKT; 66 | 67 | 68 | typedef struct _WIN32_COMMAND { // ����WIN32����ӿڽṹ 69 | union { 70 | ULONG mFunction; // ����ʱָ�����ܴ�����߹ܵ��� 71 | NTSTATUS mStatus; // ���ʱ���ز���״̬ 72 | }; 73 | ULONG mLength; // ��ȡ����,���غ������ݵij��� 74 | union { 75 | mUSB_SETUP_PKT mSetupPkt; // USB���ƴ���Ľ����׶ε��������� 76 | UCHAR mBuffer[ 512]; // ���ݻ�����,����Ϊ0��255B 77 | }; 78 | } mWIN32_COMMAND, *mPWIN32_COMMAND; 79 | // WIN32Ӧ�ò�ӿ����� 80 | #define IOCTL_CH341_COMMAND ( FILE_DEVICE_UNKNOWN << 16 | FILE_ANY_ACCESS << 14 | 0x0f34 << 2 | METHOD_BUFFERED ) // ר�ýӿ� 81 | 82 | #define mWIN32_COMMAND_HEAD mOFFSET( mWIN32_COMMAND, mBuffer ) // WIN32����ӿڵ�ͷ���� 83 | 84 | #define mCH341_MAX_NUMBER 32 // ���ͬʱ���ӵ�CH341/7�豸���� 85 | 86 | #define mMAX_BUFFER_LENGTH 0x1000 // ���ݻ�������󳤶�4096 87 | 88 | #define mMAX_COMMAND_LENGTH ( mWIN32_COMMAND_HEAD + mMAX_BUFFER_LENGTH ) // ������ݳ��ȼ�������ṹͷ�ij��� 89 | 90 | #define mDEFAULT_BUFFER_LEN 0x0400 // ���ݻ�����Ĭ�ϳ���1024 91 | 92 | #define mDEFAULT_COMMAND_LEN ( mWIN32_COMMAND_HEAD + mDEFAULT_BUFFER_LEN ) // Ĭ�����ݳ��ȼ�������ṹͷ�ij��� 93 | 94 | // CH341�˵��ַ 95 | #define mCH347_ENDP_DATA_UP 0x86 // CH347�����ݿ��ϴ��˵�ĵ�ַ 96 | #define mCH347_ENDP_DATA_DOWN 0x06 // CH347�����ݿ��´��˵�ĵ�ַ 97 | 98 | // �豸��ӿ��ṩ�Ĺܵ��������� 99 | #define mPipeDeviceCtrl 0x00000004 // CH347���ۺϿ��ƹܵ� 100 | #define mPipeDataUp 0x00000006 // CH347�����ݿ��ϴ��ܵ� 101 | #define mPipeDataDown 0x00000007 // CH347�����ݿ��´��ܵ� 102 | 103 | // Ӧ�ò�ӿڵĹ��ܴ��� 104 | #define mFuncNoOperation 0x00000000 // �޲��� 105 | #define mFuncGetVersion 0x00000001 // ��ȡ��������汾�� 106 | #define mFuncGetConfig 0x00000002 // ��ȡUSB�豸���������� 107 | #define mFuncSetTimeout 0x00000009 // ����USBͨѶ��ʱ 108 | #define mFuncSetExclusive 0x0000000b // ���ö�ռʹ�� 109 | #define mFuncResetDevice 0x0000000c // ��λUSB�豸 110 | #define mFuncResetPipe 0x0000000d // ��λUSB�ܵ� 111 | #define mFuncAbortPipe 0x0000000e // ȡ��USB�ܵ����������� 112 | #define mFuncBufferMode 0x00000020 // �趨�����ϴ�ģʽ����ѯ�������е����ݳ��� 113 | #define mFuncBufferModeDn 0x00000021 // �趨�����´�ģʽ����ѯ�������е����ݳ��� 114 | #define mFuncGetVersionEx 0x00000022 // ��ȡ��������汾�ż�оƬ�ͺ� 115 | // USB�豸��׼������� 116 | #define mUSB_CLR_FEATURE 0x01 117 | #define mUSB_SET_FEATURE 0x03 118 | #define mUSB_GET_STATUS 0x00 119 | #define mUSB_SET_ADDRESS 0x05 120 | #define mUSB_GET_DESCR 0x06 121 | #define mUSB_SET_DESCR 0x07 122 | #define mUSB_GET_CONFIG 0x08 123 | #define mUSB_SET_CONFIG 0x09 124 | #define mUSB_GET_INTERF 0x0a 125 | #define mUSB_SET_INTERF 0x0b 126 | #define mUSB_SYNC_FRAME 0x0c 127 | 128 | // CH341���ƴ���ij���ר���������� 129 | #define mCH341_VENDOR_READ 0xC0 // ͨ�����ƴ���ʵ�ֵ�CH341����ר�ö����� 130 | #define mCH341_VENDOR_WRITE 0x40 // ͨ�����ƴ���ʵ�ֵ�CH341����ר��д���� 131 | 132 | #define mCH341A_CMD_I2C_STREAM 0xAA // I2C�ӿڵ������,�Ӵ��ֽڿ�ʼΪI2C������ 133 | #define mCH341A_CMD_UIO_STREAM 0xAB // UIO�ӿڵ������,�Ӵ��ֽڿ�ʼΪ������ 134 | #define mCH341A_CMD_PIO_STREAM 0xAE // PIO�ӿڵ������,�Ӵ��ֽڿ�ʼΪ������ 135 | // CH341A���ƴ���ij���ר��������� 136 | #define mCH341A_BUF_CLEAR 0xB2 // ���δ��ɵ����� 137 | #define mCH341A_I2C_CMD_X 0x54 // ����I2C�ӿڵ�����,����ִ�� 138 | #define mCH341A_DELAY_MS 0x5E // ������Ϊ��λ��ʱָ��ʱ�� 139 | #define mCH341A_GET_VER 0x5F // ��ȡоƬ�汾 140 | 141 | #define mCH341A_CMD_I2C_STM_STA 0x74 // I2C�ӿڵ�������:������ʼλ 142 | #define mCH341A_CMD_I2C_STM_STO 0x75 // I2C�ӿڵ�������:����ֹͣλ 143 | #define mCH341A_CMD_I2C_STM_OUT 0x80 // I2C�ӿڵ�������:�������,λ5-λ0Ϊ����,�����ֽ�Ϊ����,0������ֻ����һ���ֽڲ�����Ӧ�� 144 | #define mCH341A_CMD_I2C_STM_IN 0xC0 // I2C�ӿڵ�������:��������,λ5-λ0Ϊ����,0������ֻ����һ���ֽڲ�������Ӧ�� 145 | #define mCH341A_CMD_I2C_STM_MAX ( min( 0x3F, mCH341_PACKET_LENGTH ) ) // I2C�ӿڵ�������������������������ݵ���󳤶� 146 | #define mCH341A_CMD_I2C_STM_SET 0x60 // I2C�ӿڵ�������:���ò���,λ2=SPI��I/O��(0=���뵥��,1=˫��˫��),λ1λ0=I2C�ٶ�(00=����,01=��׼,10=����,11=����) 147 | #define mCH341A_CMD_I2C_STM_US 0x40 // I2C�ӿڵ�������:��΢��Ϊ��λ��ʱ,λ3-λ0Ϊ��ʱֵ 148 | #define mCH341A_CMD_I2C_STM_MS 0x50 // I2C�ӿڵ�������:������Ϊ��λ��ʱ,λ3-λ0Ϊ��ʱֵ 149 | #define mCH341A_CMD_I2C_STM_DLY 0x0F // I2C�ӿڵ�����������������ʱ�����ֵ 150 | #define mCH341A_CMD_I2C_STM_END 0x00 // I2C�ӿڵ�������:�������ǰ���� 151 | 152 | #define mCH341A_CMD_UIO_STM_IN 0x00 // UIO�ӿڵ�������:��������D7-D0 153 | #define mCH341A_CMD_UIO_STM_DIR 0x40 // UIO�ӿڵ�������:�趨I/O����D5-D0,λ5-λ0Ϊ�������� 154 | #define mCH341A_CMD_UIO_STM_OUT 0x80 // UIO�ӿڵ�������:�������D5-D0,λ5-λ0Ϊ���� 155 | #define mCH341A_CMD_UIO_STM_US 0xC0 // UIO�ӿڵ�������:��΢��Ϊ��λ��ʱ,λ5-λ0Ϊ��ʱֵ 156 | #define mCH341A_CMD_UIO_STM_END 0x20 // UIO�ӿڵ�������:�������ǰ���� 157 | 158 | #define MAX_DEVICE_PATH_SIZE 128 // �豸���Ƶ�����ַ��� 159 | #define MAX_DEVICE_ID_SIZE 64 // �豸ID������ַ��� 160 | #endif 161 | 162 | // �����ӿ� 163 | #define CH347_USB_VENDOR 0 164 | #define CH347_USB_HID 2 165 | #define CH347_USB_VCP 3 166 | 167 | // CH347_USB_VENDOR֧��CH341/CH347T/CH347F/CH339W 168 | #define CHIP_TYPE_CH341 0 169 | #define CHIP_TYPE_CH347 1 170 | #define CHIP_TYPE_CH347F 2 171 | #define CHIP_TYPE_CH339W 3 172 | #define CHIP_TYPE_CH347T CHIP_TYPE_CH347 173 | 174 | // оƬ���ܽӿ����� 175 | #define CH347_FUNC_UART 0 176 | #define CH347_FUNC_SPI_IIC 1 177 | #define CH347_FUNC_JTAG_IIC 2 178 | #define CH347_FUNC_JTAG_IIC_SPI 3 // CH347Fͬʱ֧��SPI\I2C\JTAG�ӿ� 179 | 180 | #define DEFAULT_READ_TIMEOUT 500 // Ĭ�϶���ʱ������ 181 | #define DEFAULT_WRITE_TIMEOUT 500 // Ĭ��д��ʱ������ 182 | 183 | #define mCH347_PACKET_LENGTH 512 // CH347֧�ֵ����ݰ��ij��� 184 | 185 | #pragma pack(1) 186 | 187 | //SPI���������� 188 | typedef struct _SPI_CONFIG{ 189 | UCHAR iMode; // 0-3:SPI Mode0/1/2/3 190 | UCHAR iClock; // 0=60MHz, 1=30MHz, 2=15MHz, 3=7.5MHz, 4=3.75MHz, 5=1.875MHz, 6=937.5KHz��7=468.75KHz 191 | UCHAR iByteOrder; // 0=��λ��ǰ(LSB), 1=��λ��ǰ(MSB) 192 | USHORT iSpiWriteReadInterval; // SPI�ӿڳ����ȡд�����������λΪuS 193 | UCHAR iSpiOutDefaultData; // SPI������ʱĬ��������� 194 | ULONG iChipSelect; // Ƭѡ����, λ7Ϊ0�����Ƭѡ����, λ7Ϊ1�������Ч: λ1λ0Ϊ00/01�ֱ�ѡ��CS1/CS2������Ϊ�͵�ƽ��ЧƬѡ 195 | UCHAR CS1Polarity; // λ0��ƬѡCS1���Կ��ƣ�0���͵�ƽ��Ч��1���ߵ�ƽ��Ч�� 196 | UCHAR CS2Polarity; // λ0��ƬѡCS2���Կ��ƣ�0���͵�ƽ��Ч��1���ߵ�ƽ��Ч�� 197 | USHORT iIsAutoDeativeCS; // ������ɺ��Ƿ��Զ�����Ƭѡ 198 | USHORT iActiveDelay; // ����Ƭѡ��ִ�ж�д��������ʱʱ��,��λus 199 | ULONG iDelayDeactive; // ����Ƭѡ��ִ�ж�д��������ʱʱ��,��λus 200 | }mSpiCfgS,*mPSpiCfgS; 201 | 202 | //�豸��Ϣ 203 | typedef struct _DEV_INFOR{ 204 | UCHAR iIndex; // ��ǰ����� 205 | UCHAR DevicePath[MAX_PATH]; // �豸������,����CreateFile 206 | UCHAR UsbClass; // ������� 0:CH347_USB_CH341, 2:CH347_USB_HID, 3:CH347_USB_VCP 207 | UCHAR FuncType; // ������� 0:CH347_FUNC_UART, 1:CH347_FUNC_SPI_I2C, 2:CH347_FUNC_JTAG_I2C, 3:CH347_FUNC_JTAG_IIC_SPI 208 | CHAR DeviceID[64]; // USB\VID_xxxx&PID_xxxx 209 | UCHAR ChipMode; // оƬ����ģʽ,0:Mode0(UART0/1); 1:Mode1(Uart1+SPI+I2C); 2:Mode2(HID Uart1+SPI+I2C) 3:Mode3(Uart1+Jtag) 4:CH347F(Uart*2+Jtag/SPI/IIC) 210 | HANDLE DevHandle; // �豸��� 211 | USHORT BulkOutEndpMaxSize; // �����ϴ��˵��С 212 | USHORT BulkInEndpMaxSize; // �����´��˵��С 213 | UCHAR UsbSpeedType; // USB�ٶ����ͣ�0:FS,1:HS,2:SS 214 | UCHAR CH347IfNum; // USB�ӿں�: CH347T: IF0:UART; IF1:SPI/IIC/JTAG/GPIO 215 | // CH347F: IF0:UART0; IF1:UART1; IF 2:SPI/IIC/JTAG/GPIO 216 | UCHAR DataUpEndp; // �����ϴ��˵��ַ 217 | UCHAR DataDnEndp; // �����´��˵��ַ 218 | CHAR ProductString[64]; // USB��Ʒ�ַ��� 219 | CHAR ManufacturerString[64]; // USB�����ַ��� 220 | ULONG WriteTimeout; // USBд��ʱ 221 | ULONG ReadTimeout; // USB����ʱ 222 | CHAR FuncDescStr[64]; // �ӿڹ��������� 223 | UCHAR FirewareVer; // �̼��汾,ʮ������ֵ 224 | }mDeviceInforS,*mPDeviceInforS; 225 | 226 | #pragma pack() 227 | 228 | // CH347��ģʽ���ú���,֧��CH347����ģʽ�µĴ򿪡��رա�USB����USBд������HID 229 | //��USB�豸 230 | HANDLE WINAPI CH347OpenDevice(ULONG DevI); // ָ���豸��� 231 | 232 | //�ر�USB�豸 233 | BOOL WINAPI CH347CloseDevice(ULONG iIndex); // ָ���豸��� 234 | 235 | // ��ȡ�豸USB���к� 236 | BOOL WINAPI CH347GetSerialNumber(ULONG iIndex, // ָ���豸��� 237 | PUCHAR iSerialNumberStr); // ָ���ȡ�����豸���к� 238 | 239 | // ��ȡ�豸��Ϣ 240 | BOOL WINAPI CH347GetDeviceInfor(ULONG iIndex, // ָ���豸��� 241 | mDeviceInforS *DevInformation); // ָ���ȡ�����豸��Ϣ 242 | 243 | // ��ȡCH347оƬ����:0:CHIP_TYPE_CH341��1:CHIP_TYPE_CH347/CHIP_TYPE_CH347T,2:CHIP_TYPE_CH347F��3:CHIP_TYPE_CH339W 244 | UCHAR WINAPI CH347GetChipType(ULONG iIndex ); // ָ���豸��� 245 | 246 | // ��ȡ�����汾����汾���豸�汾��оƬ����(CH341(FS)/CH347HS) 247 | BOOL WINAPI CH347GetVersion(ULONG iIndex, 248 | PUCHAR iDriverVer, 249 | PUCHAR iDLLVer, 250 | PUCHAR ibcdDevice, 251 | PUCHAR iChipType); //CHIP_TYPE_CH341/7 252 | 253 | typedef VOID ( CALLBACK * mPCH347_NOTIFY_ROUTINE ) ( // �豸���֪ͨ�¼��ص����� 254 | ULONG iEventStatus ); // �豸����¼��͵�ǰ״̬(�����ж���): 0=�豸�γ��¼�, 3=�豸�����¼� 255 | 256 | #define CH347_DEVICE_ARRIVAL 3 // �豸�����¼�,�Ѿ����� 257 | #define CH347_DEVICE_REMOVE_PEND 1 // �豸��Ҫ�γ� 258 | #define CH347_DEVICE_REMOVE 0 // �豸�γ��¼�,�Ѿ��γ� 259 | 260 | // �趨�豸�¼�֪ͨ���� 261 | BOOL WINAPI CH347SetDeviceNotify(ULONG iIndex, // ָ���豸���,0��Ӧ��һ���豸 262 | PCHAR iDeviceID, // ��ѡ����,ָ���ַ���,ָ������ص��豸��ID,�ַ�����\0��ֹ 263 | mPCH347_NOTIFY_ROUTINE iNotifyRoutine ); // ָ���豸�¼��ص�����,ΪNULL��ȡ���¼�֪ͨ,�����ڼ�⵽�¼�ʱ���øó��� 264 | 265 | // ��ȡUSB���ݿ� 266 | BOOL WINAPI CH347ReadData( ULONG iIndex, // ָ���豸��� 267 | PVOID oBuffer, // ָ��һ���㹻��Ļ�����,���ڱ����ȡ������ 268 | PULONG ioLength ); // ָ�򳤶ȵ�Ԫ,����ʱΪ׼����ȡ�ij���,���غ�Ϊʵ�ʶ�ȡ�ij��� 269 | 270 | // дȡUSB���ݿ� 271 | BOOL WINAPI CH347WriteData(ULONG iIndex, // ָ���豸��� 272 | PVOID iBuffer, // ָ��һ��������,����׼��д�������� 273 | PULONG ioLength ); // ָ�򳤶ȵ�Ԫ,����ʱΪ׼��д���ij���,���غ�Ϊʵ��д���ij��� 274 | 275 | // ����USB���ݶ�д�ij�ʱ 276 | BOOL WINAPI CH347SetTimeout(ULONG iIndex, // ָ���豸��� 277 | ULONG iWriteTimeout, // ָ��USBд�����ݿ�ij�ʱʱ��,�Ժ���mSΪ��λ,0xFFFFFFFFָ������ʱ(Ĭ��ֵ) 278 | ULONG iReadTimeout ); // ָ��USB��ȡ���ݿ�ij�ʱʱ��,�Ժ���mSΪ��λ,0xFFFFFFFFָ������ʱ(Ĭ��ֵ) 279 | 280 | /***************SPI********************/ 281 | // SPI��������ʼ�� 282 | BOOL WINAPI CH347SPI_Init(ULONG iIndex, // ָ���豸��� 283 | mSpiCfgS *SpiCfg); // ָ��SPI���ýṹ�� 284 | 285 | // ����SPIʱ��Ƶ�ʣ����øýӿں������µ���CH347SPI_Init���г�ʼ�� 286 | BOOL WINAPI CH347SPI_SetFrequency(ULONG iIndex, // ָ���豸��� 287 | ULONG iSpiSpeedHz);// ����SPIʱ�ӣ���λΪHZ 288 | 289 | // ����SPI����λ�� 290 | BOOL WINAPI CH347SPI_SetDataBits(ULONG iIndex, // ָ���豸��� 291 | UCHAR iDataBits); // 0=8bit��1=16bit 292 | 293 | // ��ȡSPI������������Ϣ 294 | BOOL WINAPI CH347SPI_GetCfg(ULONG iIndex,mSpiCfgS *SpiCfg); 295 | 296 | // ����Ƭѡ״̬,ʹ��ǰ���ȵ���CH347SPI_Init��CS�������� 297 | BOOL WINAPI CH347SPI_ChangeCS(ULONG iIndex, // ָ���豸��� 298 | UCHAR iStatus); // 0=����Ƭѡ,1=����Ƭѡ 299 | 300 | // ����SPIƬѡ 301 | BOOL WINAPI CH347SPI_SetChipSelect(ULONG iIndex, // ָ���豸��� 302 | USHORT iEnableSelect, // �Ͱ�λΪCS1���߰�λΪCS2; �ֽ�ֵΪ1=����CS,Ϊ0=���Դ�CS���� 303 | USHORT iChipSelect, // �Ͱ�λΪCS1���߰�λΪCS2;Ƭѡ���,0=����Ƭѡ,1=����Ƭѡ 304 | ULONG iIsAutoDeativeCS, // ��16λΪCS1����16λΪCS2;������ɺ��Ƿ��Զ�����Ƭѡ 305 | ULONG iActiveDelay, // ��16λΪCS1����16λΪCS2;����Ƭѡ��ִ�ж�д��������ʱʱ��,��λus 306 | ULONG iDelayDeactive); // ��16λΪCS1����16λΪCS2;����Ƭѡ��ִ�ж�д��������ʱʱ��,��λus 307 | 308 | // SPI4д���� 309 | BOOL WINAPI CH347SPI_Write(ULONG iIndex, // ָ���豸��� 310 | ULONG iChipSelect, // Ƭѡ����, λ7Ϊ0�����Ƭѡ����, λ7Ϊ1����Ƭѡ���� 311 | ULONG iLength, // ׼������������ֽ��� 312 | ULONG iWriteStep, // ׼����ȡ�ĵ�����ij��� 313 | PVOID ioBuffer); // ָ��һ��������,����׼����MOSIд�������� 314 | 315 | // SPI4������.������д���ݣ�Ч�ʽ�CH347SPI_WriteRead�ߺܶ� 316 | BOOL WINAPI CH347SPI_Read(ULONG iIndex, // ָ���豸��� 317 | ULONG iChipSelect, // Ƭѡ����, λ7Ϊ0�����Ƭѡ����, λ7Ϊ1����Ƭѡ���� 318 | ULONG oLength, // ׼���������ֽ��� 319 | PULONG iLength, // ׼������������ֽ��� 320 | PVOID ioBuffer); // ָ��һ��������,����׼����DOUTд��������,���غ��Ǵ�DIN��������� 321 | 322 | // ����SPI������,4�߽ӿ� 323 | BOOL WINAPI CH347SPI_WriteRead(ULONG iIndex, // ָ���豸��� 324 | ULONG iChipSelect, // Ƭѡ����, λ7Ϊ0�����Ƭѡ����, λ7Ϊ1�����Ƭѡ 325 | ULONG iLength, // ׼������������ֽ��� 326 | PVOID ioBuffer ); // ָ��һ��������,����׼����DOUTд��������,���غ��Ǵ�DIN��������� 327 | 328 | // ����SPI������,4�߽ӿ� 329 | BOOL WINAPI CH347StreamSPI4(ULONG iIndex, // ָ���豸��� 330 | ULONG iChipSelect, // Ƭѡ����, λ7Ϊ0�����Ƭѡ����, λ7Ϊ1�������Ч 331 | ULONG iLength, // ׼������������ֽ��� 332 | PVOID ioBuffer ); // ָ��һ��������,����׼����DOUTд��������,���غ��Ǵ�DIN��������� 333 | 334 | /***************JTAG********************/ 335 | // JTAG�ӿڳ�ʼ��������JTAGͨ���ٶ� 336 | BOOL WINAPI CH347Jtag_INIT(ULONG iIndex, // ָ���豸��� 337 | UCHAR iClockRate); // ͨ���ٶȣ�0=468.75KHz,1=937.5KHz,2=1.875MHz,3=3.75MHz,4=7.5MHz,5=15MHz,6=30MHz,7=60MHz 338 | 339 | // ��ȡJtag�ٶ����� 340 | BOOL WINAPI CH347Jtag_GetCfg(ULONG iIndex, // ָ���豸��� 341 | UCHAR *ClockRate); // ͨ���ٶȣ���ЧֵΪ0-7��ֵԽ��ͨ���ٶ�Խ�� 342 | 343 | 344 | // �ı�TMS��ֵ������״̬�л� 345 | BOOL WINAPI CH347Jtag_TmsChange(ULONG iIndex, // �豸��� 346 | PUCHAR tmsValue, // �����л���TMSλֵ,���ֽ�Ϊ��λ 347 | ULONG Step, // tmsValue�ڴ洢��TMS��Чλ�� 348 | ULONG Skip); // ��Ч��ʼλ 349 | 350 | // ��Shift-DR/IR״̬���ж�д��ִ��������Exit DR/IR 351 | // ״̬��:Shift-DR/IR.RW.->Exit DR/IR 352 | BOOL WINAPI CH347Jtag_IoScan(ULONG iIndex, 353 | PUCHAR DataBits, //��Ҫ���д��������λ 354 | ULONG DataBitsNb, //��Ҫ�������ݵ�λ�� 355 | BOOL IsRead); //�Ƿ���Ҫ��ȡ���� 356 | 357 | // ����Shift-DR/IR״̬���ж�д,ִ����ɺ�,�������һ�������л�״̬��Exit DR/IR;�������,��ͣ��Shift-DR/IR״̬ 358 | // ״̬��:Shift-DR/IR.RW..->[Exit DR/IR] 359 | BOOL WINAPI CH347Jtag_IoScanT(ULONG iIndex, // ָ���豸��� 360 | PUCHAR DataBits, // ��Ҫ���д��������λ 361 | ULONG DataBitsNb, // ��Ҫ�������ݵ�λ�� 362 | BOOL IsRead, // �Ƿ���Ҫ��ȡ���� 363 | BOOL IsLastPkt); // �Ƿ�Ϊ���һ�� 364 | 365 | // JTAG��λTap״̬����.������������TCK��TMSΪ�߽��ɽ�״̬����ΪTest-Logic Reset״̬ 366 | ULONG WINAPI CH347Jtag_Reset(ULONG iIndex); // ָ���豸��� 367 | 368 | // ����TRST���Ӳ����λ 369 | BOOL WINAPI CH347Jtag_ResetTrst(ULONG iIndex, // ָ���豸��� 370 | BOOL iLevel); // 0=����Ϊ�ͣ�1=����Ϊ�� 371 | 372 | // λ����ʽJTAG IR/DR���ݶ�д.�������������ݵĶ�д����ָ�������״̬���л��ȿ����ഫ�䡣���������ݴ��䣬����ʹ��CH347Jtag_WriteRead_Fast 373 | // �������4096�ֽ�Ϊ��λ������д 374 | // ״̬��:Run-Test->Shift-IR/DR..->Exit IR/DR -> Run-Test 375 | BOOL WINAPI CH347Jtag_WriteRead(ULONG iIndex, // ָ���豸��� 376 | BOOL IsDR, // =TRUE: DR���ݶ�д,=FALSE:IR���ݶ�д 377 | ULONG iWriteBitLength, // д����,׼��д���ij��� 378 | PVOID iWriteBitBuffer, // ָ��һ��������,����׼��д�������� 379 | PULONG oReadBitLength, // ָ�򳤶ȵ�Ԫ,���غ�Ϊʵ�ʶ�ȡ�ij��� 380 | PVOID oReadBitBuffer ); // ָ��һ���㹻��Ļ�����,���ڱ����ȡ������ 381 | 382 | // JTAG IR/DR����������д,���ڶ��ֽ�������д����JTAG�̼����ز�������Ӳ����4K������������д��������Ȳ�����4096�ֽڡ���������С�����е��� 383 | // ״̬��:Run-Test->Shift-IR/DR..->Exit IR/DR -> Run-Test 384 | BOOL WINAPI CH347Jtag_WriteRead_Fast(ULONG iIndex, // ָ���豸��� 385 | BOOL IsDR, // =TRUE: DR���ݶ�д,=FALSE:IR���ݶ�д 386 | ULONG iWriteBitLength, // д����,׼��д���ij��� 387 | PVOID iWriteBitBuffer, // ָ��һ��������,����׼��д�������� 388 | PULONG oReadBitLength, // ָ�򳤶ȵ�Ԫ,���غ�Ϊʵ�ʶ�ȡ�ij��� 389 | PVOID oReadBitBuffer ); // ָ��һ���㹻��Ļ�����,���ڱ����ȡ������ 390 | 391 | // λ����ʽJTAG IR/DR���ݶ�д.�������������ݵĶ�д����ָ�������״̬���л��ȿ����ഫ�䡣���������ݴ��䣬����ʹ��CH347Jtag_WriteRead_Fast 392 | // �������4096�ֽ�Ϊ��λ������д 393 | // ״̬��:Run-Test-> Shift-IR/DR..->Exit IR/DR -> Run-Test 394 | BOOL WINAPI CH347Jtag_WriteReadEx(ULONG iIndex, // ָ���豸��� 395 | BOOL IsInDrOrIr, // =TRUE: ��SHIFT-DR/IR״̬�������ݽ��� ==FALSE: Run-Test->Shift-IR/DR.�������ݽ���.->Exit IR/DR -> Run-Test 396 | BOOL IsDR, // =TRUE: DR���ݶ�д,=FALSE:IR���ݶ�д 397 | ULONG iWriteBitLength, // д����,׼��д���ij��� 398 | PVOID iWriteBitBuffer, // ָ��һ��������,����׼��д�������� 399 | PULONG oReadBitLength, // ָ�򳤶ȵ�Ԫ,���غ�Ϊʵ�ʶ�ȡ�ij��� 400 | PVOID oReadBitBuffer ); // ָ��һ���㹻��Ļ�����,���ڱ����ȡ������ 401 | 402 | // JTAG IR/DR����������д,���ڶ��ֽ�������д����JTAG�̼����ز�������Ӳ����4K������������д��������Ȳ�����4096�ֽڡ���������С�����е��� 403 | // ״̬��:Run-Test->Shift-IR/DR..->Exit IR/DR -> Run-Test 404 | BOOL WINAPI CH347Jtag_WriteRead_FastEx(ULONG iIndex, // ָ���豸��� 405 | BOOL IsInDrOrIr, // =TRUE: ��SHIFT-DR/IR״̬�������ݽ��� ==FALSE: Run-Test->Shift-IR/DR.�������ݽ���.->Exit IR/DR -> Run-Test 406 | BOOL IsDR, // =TRUE: DR���ݶ�д,=FALSE:IR���ݶ�д 407 | ULONG iWriteBitLength, // д����,׼��д���ij��� 408 | PVOID iWriteBitBuffer, // ָ��һ��������,����׼��д�������� 409 | PULONG oReadBitLength, // ָ�򳤶ȵ�Ԫ,���غ�Ϊʵ�ʶ�ȡ�ij��� 410 | PVOID oReadBitBuffer ); // ָ��һ���㹻��Ļ�����,���ڱ����ȡ������ 411 | 412 | // �����л�JTAG״̬�����谴��˳��ִ�� 413 | BOOL WINAPI CH347Jtag_SwitchTapState(UCHAR TapState); // ָ���л�����״̬ 414 | // 0:Test-Logic Reset,1:Run-Test/Idle��2:Run-Test/Idle -> Shift-DR,3:Shift-DR -> Run-Test/Idle 415 | // 4:Run-Test/Idle -> Shift-IR, 5:Shift-IR -> Run-Test/Idle, 6:Exit1-DR/IR -> Update-DR/IR -> Run-Test/Idle 416 | 417 | // �����л�JTAG״̬��,��ָ�������豸iIndex 418 | BOOL WINAPI CH347Jtag_SwitchTapStateEx(ULONG iIndex, // ָ���豸��� 419 | UCHAR TapState); // ָ���л�����״̬ 420 | 421 | // JTAG DRд,���ֽ�Ϊ��λ,���ڶ��ֽ�������д����JTAG�̼����ز����� 422 | // ״̬��:Run-Test->Shift-DR..->Exit DR -> Run-Test 423 | BOOL WINAPI CH347Jtag_ByteWriteDR(ULONG iIndex, // ָ���豸��� 424 | ULONG iWriteLength, // д����,׼��д�����ֽڳ��� 425 | PVOID iWriteBuffer); // ָ��һ��������,����׼��д�������� 426 | 427 | // JTAG DR��,���ֽ�Ϊ��λ,���ֽ��������� 428 | // ״̬��:Run-Test->Shift-DR..->Exit DR -> Run-Test 429 | BOOL WINAPI CH347Jtag_ByteReadDR(ULONG iIndex, // ָ���豸��� 430 | PULONG oReadLength, // ָ�򳤶ȵ�Ԫ,���غ�Ϊʵ�ʶ�ȡ���ֽڳ��� 431 | PVOID oReadBuffer ); // ָ��һ���㹻��Ļ�����,���ڱ����ȡ������ 432 | 433 | // JTAG IRд,���ֽ�Ϊ��λ,���ֽ�����д�� 434 | // ״̬��:Run-Test->Shift-IR..->Exit IR -> Run-Test 435 | BOOL WINAPI CH347Jtag_ByteWriteIR(ULONG iIndex, // ָ���豸��� 436 | ULONG iWriteLength, // д����,׼��д�����ֽڳ��� 437 | PVOID iWriteBuffer); // ָ��һ��������,����׼��д�������� 438 | 439 | // JTAG IR��,���ֽ�Ϊ��λ,���ֽ�������д�� 440 | // ״̬��:Run-Test->Shift-IR..->Exit IR -> Run-Test 441 | BOOL WINAPI CH347Jtag_ByteReadIR(ULONG iIndex, // ָ���豸��� 442 | PULONG oReadLength, // ָ�򳤶ȵ�Ԫ,���غ�Ϊʵ�ʶ�ȡ���ֽڳ��� 443 | PVOID oReadBuffer ); // ָ��һ���㹻��Ļ�����,���ڱ����ȡ������ 444 | 445 | // λ����ʽJTAG DR����д.�������������ݵĶ�д����ָ�������״̬���л��ȿ����ഫ�䡣���������ݴ��䣬����ʹ��USB20Jtag_ByeWriteDR 446 | // ״̬��:Run-Test->Shift-DR..->Exit DR -> Run-Test 447 | BOOL WINAPI CH347Jtag_BitWriteDR(ULONG iIndex, // ָ���豸��� 448 | ULONG iWriteBitLength, // ָ�򳤶ȵ�Ԫ,���غ�Ϊʵ�ʶ�ȡ���ֽڳ��� 449 | PVOID iWriteBitBuffer ); // ָ��һ���㹻��Ļ�����,���ڱ����ȡ������ 450 | 451 | // λ����ʽJTAG IR����д.�������������ݵĶ�д����ָ�������״̬���л��ȿ����ഫ�䡣���������ݴ��䣬����ʹ��USB20Jtag_ByteWriteIR 452 | // ״̬��:Run-Test->Shift-IR..->Exit IR -> Run-Test 453 | BOOL WINAPI CH347Jtag_BitWriteIR(ULONG iIndex, // ָ���豸��� 454 | ULONG iWriteBitLength, // ָ�򳤶ȵ�Ԫ,���غ�Ϊʵ�ʶ�ȡ���ֽڳ��� 455 | PVOID iWriteBitBuffer ); // ָ��һ���㹻��Ļ�����,���ڱ����ȡ������ 456 | 457 | // λ����ʽJTAG IR���ݶ�.�������������ݵĶ�д����ָ�������״̬���л��ȡ����������ݴ��䣬����ʹ��USB20Jtag_ByteReadIR 458 | // ״̬��:Run-Test->Shift-IR..->Exit IR -> Run-Test 459 | BOOL WINAPI CH347Jtag_BitReadIR(ULONG iIndex, // ָ���豸��� 460 | PULONG oReadBitLength, // ָ�򳤶ȵ�Ԫ,���غ�Ϊʵ�ʶ�ȡ���ֽڳ��� 461 | PVOID oReadBitBuffer ); // ָ��һ���㹻��Ļ�����,���ڱ����ȡ������ 462 | 463 | // λ����ʽJTAG DR���ݶ�.�������������ݵĶ�д���������͸������ݴ��䣬����ʹ��USB20Jtag_ByteReadDR 464 | // ״̬��:Run-Test->Shift-DR..->Exit DR -> Run-Test 465 | BOOL WINAPI CH347Jtag_BitReadDR(ULONG iIndex, // ָ���豸��� 466 | PULONG oReadBitLength, // ָ�򳤶ȵ�Ԫ,���غ�Ϊʵ�ʶ�ȡ���ֽڳ��� 467 | PVOID oReadBitBuffer ); // ָ��һ���㹻��Ļ�����,���ڱ����ȡ������ 468 | 469 | /***************GPIO********************/ 470 | // ��ȡCH347��GPIO��������ŵ�ƽֵ 471 | BOOL WINAPI CH347GPIO_Get(ULONG iIndex, // ָ���豸��� 472 | UCHAR *iDir, // ���ŷ���:GPIO0-7��Ӧλ0-7, 0=���룻1=��� 473 | UCHAR *iData); // GPIO0��ƽ:GPIO0-7��Ӧλ0-7,0=�͵�ƽ��1=�ߵ�ƽ) 474 | 475 | // ����CH347��GPIO��������ŵ�ƽֵ 476 | BOOL WINAPI CH347GPIO_Set(ULONG iIndex, // ָ���豸��� 477 | UCHAR iEnable, // ������Ч��־:��Ӧλ0-7,��ӦGPIO0-7. 478 | UCHAR iSetDirOut, // ����I/O����,ijλ��0���Ӧ����Ϊ����,ijλ��1���Ӧ����Ϊ���.GPIO0-7��Ӧλ0-7. 479 | UCHAR iSetDataOut); // �������,���I/O����Ϊ���,��ôijλ��0ʱ��Ӧ��������͵�ƽ,ijλ��1ʱ��Ӧ��������ߵ�ƽ 480 | 481 | 482 | typedef VOID ( CALLBACK * mPCH347_INT_ROUTINE ) ( // �жϷ������ 483 | PUCHAR iStatus ); // �ж�״̬����,�ο������λ˵�� 484 | // 8���ֽ�GPIO0-7����״̬.ÿ�ֽ�λ��������: 485 | // λ7����ǰ��GPIO0����0�����룻1������� 486 | // λ6����ǰ��GPIO0��ƽ��0���͵�ƽ��1���ߵ�ƽ�� 487 | // λ5����ǰ��GPIO0�Ƿ�����Ϊ�жϣ�0����ѯģʽ��1���ж�ģʽ�� 488 | // λ4-3������GPIO0���ж�ģʽ��00���½��ش�����01�������ش���;10��˫���ش�����11: ����; 489 | // λ2-0�������� 490 | 491 | // �趨GPIO�жϷ������ 492 | BOOL WINAPI CH347SetIntRoutine(ULONG iIndex, // ָ���豸��� 493 | UCHAR Int0PinN, // �ж�0 GPIO���ź�,����7:�����ô��ж�Դ; Ϊ0-7��Ӧgpio0-7 494 | UCHAR Int0TripMode, // �ж�0����: 00:�½��ش���; 01:�����ش���; 02:˫���ش���; 03:����; 495 | UCHAR Int1PinN, // �ж�1 GPIO���ź�,����7�����ô��ж�Դ,Ϊ0-7��Ӧgpio0-7 496 | UCHAR Int1TripMode, // �ж�1����: 00:�½��ش���; 01:�����ش���; 02:˫���ش���; 03:����; 497 | mPCH347_INT_ROUTINE iIntRoutine );// ָ���жϷ������,ΪNULL��ȡ���жϷ���,�������ж�ʱ���øó��� 498 | 499 | // ��ȡ�ж����� 500 | BOOL WINAPI CH347ReadInter(ULONG iIndex, // ָ���豸��� 501 | PUCHAR iStatus ); // ָ��8�ֽڵ�Ԫ,�ֱ�ΪGPIO0-7����״̬,ÿ���ֽ�λ˵���ο��жϷ������iStatusλ˵�� 502 | 503 | // �����ж����ݶ����� 504 | BOOL WINAPI CH347AbortInter(ULONG iIndex ); // ָ���豸��� 505 | 506 | // ����IAP�̼�����ģʽ 507 | BOOL WINAPI CH347StartIapFwUpate(ULONG iIndex, 508 | ULONG FwSize); // �̼����� 509 | 510 | /**************HID/VCP����**********************/ 511 | // �򿪴��� 512 | HANDLE WINAPI CH347Uart_Open(ULONG iIndex); // ָ���豸��� 513 | 514 | // �رմ��� 515 | BOOL WINAPI CH347Uart_Close(ULONG iIndex); // ָ���豸��� 516 | 517 | BOOL WINAPI CH347Uart_SetDeviceNotify( // �趨�豸�¼�֪ͨ���� 518 | ULONG iIndex, // ָ���豸���,0��Ӧ��һ���豸 519 | PCHAR iDeviceID, // ��ѡ����,ָ���ַ���,ָ������ص��豸��ID,�ַ�����\0��ֹ 520 | mPCH347_NOTIFY_ROUTINE iNotifyRoutine ); // ָ���豸�¼��ص�����,ΪNULL��ȡ���¼�֪ͨ,�����ڼ�⵽�¼�ʱ���øó��� 521 | 522 | // ��ȡUARTӲ������ 523 | BOOL WINAPI CH347Uart_GetCfg(ULONG iIndex, // ָ���豸��� 524 | PULONG BaudRate, // ������ 525 | PUCHAR ByteSize, // ����λ��(5,6,7,8,16) 526 | PUCHAR Parity, // У��λ(0��None; 1��Odd; 2��Even; 3��Mark; 4��Space) 527 | PUCHAR StopBits, // ֹͣλ��(0��1ֹͣλ; 1��1.5ֹͣλ; 2��2ֹͣλ)�� 528 | PUCHAR ByteTimeout); // �ֽڳ�ʱ 529 | 530 | // ����UART���� 531 | BOOL WINAPI CH347Uart_Init(ULONG iIndex, // ָ���豸��� 532 | DWORD BaudRate, // ������ 533 | UCHAR ByteSize, // ����λ��(5,6,7,8,16) 534 | UCHAR Parity, // У��λ(0��None; 1��Odd; 2��Even; 3��Mark; 4��Space) 535 | UCHAR StopBits, // ֹͣλ��(0��1ֹͣλ; 1��1.5ֹͣλ; 2��2ֹͣλ)�� 536 | UCHAR ByteTimeout);// �ֽڳ�ʱʱ��,��λ100uS 537 | 538 | // ����USB���ݶ�д�ij�ʱ 539 | BOOL WINAPI CH347Uart_SetTimeout(ULONG iIndex, // ָ���豸��� 540 | ULONG iWriteTimeout, // ָ��USBд�����ݿ�ij�ʱʱ��,�Ժ���mSΪ��λ,0xFFFFFFFFָ������ʱ(Ĭ��ֵ) 541 | ULONG iReadTimeout ); // ָ��USB��ȡ���ݿ�ij�ʱʱ��,�Ժ���mSΪ��λ,0xFFFFFFFFָ������ʱ(Ĭ��ֵ) 542 | 543 | // ���ڶ� 544 | BOOL WINAPI CH347Uart_Read(ULONG iIndex, // ָ���豸��� 545 | PVOID oBuffer, // ָ��һ���㹻��Ļ�����,���ڱ����ȡ������ 546 | PULONG ioLength );// ָ�򳤶ȵ�Ԫ,����ʱΪ׼����ȡ�ij���,���غ�Ϊʵ�ʶ�ȡ�ij��� 547 | // ����д 548 | BOOL WINAPI CH347Uart_Write(ULONG iIndex, // ָ���豸��� 549 | PVOID iBuffer, // ָ��һ��������,����׼��д�������� 550 | PULONG ioLength );// ָ�򳤶ȵ�Ԫ,����ʱΪ׼��д���ij���,���غ�Ϊʵ��д���ij��� 551 | 552 | // ��ѯ���������ж����ֽ�δȡ��������HIDģʽ���ڣ� 553 | BOOL WINAPI CH347Uart_QueryBufUpload(ULONG iIndex, // ָ���豸��� 554 | LONGLONG *RemainBytes); // ��������δȡ�ֽ��� 555 | 556 | // ��ȡ�豸��Ϣ 557 | BOOL WINAPI CH347Uart_GetDeviceInfor(ULONG iIndex,mDeviceInforS *DevInformation); 558 | 559 | /********I2C***********/ 560 | // I2C���� 561 | BOOL WINAPI CH347I2C_Set(ULONG iIndex, // ָ���豸��� 562 | ULONG iMode ); // ָ��ģʽ,������ 563 | // λ0-λ2: I2C�ӿ��ٶ�/SCLƵ��, 000=����/20KHz,001=��׼/100KHz(Ĭ��ֵ),010=����/400KHz,011=����/750KHz,100=����/50KHz,101=��׼/200KHz��110=����/1MHz 564 | // ��������,����Ϊ0 565 | 566 | // ����I2Cʱ����չ���� 567 | BOOL WINAPI CH347I2C_SetStretch(ULONG iIndex, // ָ���豸��� 568 | BOOL iEnable); // 0=�ر�ʱ����չ���ܣ�Ĭ�Ϲرգ���1=����ʱ����չ���� 569 | 570 | // ����Ӳ���첽��ʱ,���ú�ܿ췵��,������һ��������֮ǰ��ʱָ�������� 571 | BOOL WINAPI CH347I2C_SetDelaymS(ULONG iIndex, // ָ���豸��� 572 | ULONG iDelay ) ; // ָ����ʱ�ĺ����� 573 | 574 | // ����I2C��������ģʽ 575 | BOOL WINAPI CH347I2C_SetDriverMode(ULONG iIndex, // ָ���豸��� 576 | UCHAR iMode); // 0=��©ģʽ��1=����ģʽ 577 | 578 | // ����I2C������,2�߽ӿ�,ʱ����ΪSCL����,������ΪSDA���� 579 | BOOL WINAPI CH347StreamI2C( ULONG iIndex, // ָ���豸��� 580 | ULONG iWriteLength, // ׼��д���������ֽ��� 581 | PVOID iWriteBuffer, // ָ��һ��������,����׼��д��������,���ֽ�ͨ����I2C�豸��ַ����д����λ 582 | ULONG iReadLength, // ׼����ȡ�������ֽ��� 583 | PVOID oReadBuffer ); // ָ��һ��������,���غ��Ƕ�������� 584 | 585 | // ����I2C������,2�߽ӿ�,ʱ����ΪSCL����,������ΪSDA���� 586 | BOOL WINAPI CH347StreamI2C_RetACK( // ����I2C������,2�߽ӿ�,ʱ����ΪSCL����,������ΪSDA����(׼˫��I/O),�ٶ�Լ56K�ֽ�,�����������˻�ȡ����ACK���� 587 | ULONG iIndex, // ָ���豸��� 588 | ULONG iWriteLength, // ׼��д���������ֽ��� 589 | PVOID iWriteBuffer, // ָ��һ��������,����׼��д��������,���ֽ�ͨ����I2C�豸��ַ����д����λ 590 | ULONG iReadLength, // ׼����ȡ�������ֽ��� 591 | PVOID oReadBuffer, // ָ��һ��������,���غ��Ƕ�������� 592 | PULONG rAckCount); // ָ���д���ص�ACKֵ 593 | 594 | #ifndef _CH341_DLL_H 595 | typedef enum _EEPROM_TYPE {// EEPROM�ͺ� 596 | ID_24C01, 597 | ID_24C02, 598 | ID_24C04, 599 | ID_24C08, 600 | ID_24C16, 601 | ID_24C32, 602 | ID_24C64, 603 | ID_24C128, 604 | ID_24C256, 605 | ID_24C512, 606 | ID_24C1024, 607 | ID_24C2048, 608 | ID_24C4096 609 | } EEPROM_TYPE; 610 | #endif 611 | 612 | // ��EEPROM�ж�ȡ���ݿ� 613 | BOOL WINAPI CH347ReadEEPROM(ULONG iIndex, // ָ���豸��� 614 | EEPROM_TYPE iEepromID, // ָ��EEPROM�ͺ� 615 | ULONG iAddr, // ָ�����ݵ�Ԫ�ĵ�ַ 616 | ULONG iLength, // ׼����ȡ�������ֽ��� 617 | PUCHAR oBuffer ); // ָ��һ��������,���غ��Ƕ�������� 618 | // ��EEPROM��д�����ݿ� 619 | BOOL WINAPI CH347WriteEEPROM(ULONG iIndex, // ָ���豸��� 620 | EEPROM_TYPE iEepromID, // ָ��EEPROM�ͺ� 621 | ULONG iAddr, // ָ�����ݵ�Ԫ�ĵ�ַ 622 | ULONG iLength, // ׼��д���������ֽ��� 623 | PUCHAR iBuffer ); // ָ��һ��������,����׼��д�������� 624 | 625 | //���õ�8λʱ�ӵ�������ʱʱ�䣬��������CH347T 626 | BOOL WINAPI CH347I2C_SetAckClk_DelayuS(ULONG iIndex, // ָ���豸��� 627 | ULONG iDelay); // ָ����ʱ��΢���� 628 | 629 | // �ú������ڲ�ѯָ��������CH339WоƬ��ǰ�����ӿڹ��ܵ�����״̬�� 630 | // ����ֵλ���壺 631 | // λ7 (0x80): USBתJTAGʹ��״̬��1=ʹ�ܣ�0=���ã� 632 | // λ6 (0x40): USBתSPIʹ��״̬��1=ʹ�ܣ�0=���ã� 633 | // λ5 (0x20): USBתUARTʹ�ܣ��������أ���1=ʹ�ܣ�0=���ã� 634 | // λ4 (0x10): USBתUART����ʹ�ܣ�1=ʹ�ܣ�0=���ã� 635 | // λ3 (0x08): USBתI2Cʹ��״̬��1=ʹ�ܣ�0=���ã� 636 | // λ2-λ0: ����λ 637 | UCHAR WINAPI CH339GetChipFuncState( ULONG iIndex ); // ָ���豸��� 638 | 639 | #ifdef __cplusplus 640 | } 641 | #endif 642 | 643 | #endif // _CH347_DLL_H 644 | -------------------------------------------------------------------------------- /CH347/CH347DLL_EN.H: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | ** Copyright (C) WCH 2001 - 2025 ** 3 | ** Web: http://wch.cn ** 4 | ******************************************************************************/ 5 | // USB bus interface chip CH341/7 parallel port application layer interface library. CH347/CH339W extends UART/SPI/I2C/JTAG/SWD based on the 480Mbps high-speed USB bus. 6 | // CH347-DLL V1.4 7 | // Support OS: Windows 98/ME, Windows 2000/XP, WIN7/8/10/11, and later. 8 | // Support USB chips: CH341, CH341A, CH347, CH339W 9 | // USB => Parallel, I2C, SPI, JTAG, SWD, PARALLEL, UART ... 10 | // Notes: 11 | // Copyright (C) 2025 Nanjing Qinheng Microelectronics Co., Ltd. 12 | 13 | #ifndef _CH347_DLL_H 14 | #define _CH347_DLL_H 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | #ifdef _WIN64 21 | #define mOFFSET(s, m) ((ULONG_PTR) & (((s *)0)->m)) // Defines a macro that gets the relative offset address of a structure member 22 | #else 23 | #define mOFFSET(s, m) ((ULONG) & (((s *)0)->m)) // Defines a macro that gets the relative offset address of a structure member 24 | #endif 25 | 26 | #ifndef max 27 | #define max(a, b) (((a) > (b)) ? (a) : (b)) // Determine the maximum value 28 | #endif 29 | 30 | #ifndef min 31 | #define min(a, b) (((a) < (b)) ? (a) : (b)) // Determine the minimum value 32 | #endif 33 | 34 | #ifdef ExAllocatePool 35 | #undef ExAllocatePool // Delete memory allocation with TAG 36 | #endif 37 | 38 | #ifndef NTSTATUS 39 | typedef LONG NTSTATUS; // Return status 40 | #endif 41 | 42 | // Sharing CH341WDM driver with CH341DLL 43 | #ifndef _CH341_DLL_H 44 | typedef struct _USB_SETUP_PKT { // USB control transfer structure 45 | UCHAR mUspReqType; // 00H request type 46 | UCHAR mUspRequest; // 01H request code 47 | union { 48 | struct { 49 | UCHAR mUspValueLow; // 02H Value parameter low byte 50 | UCHAR mUspValueHigh; // 03H Value parameter high byte 51 | }; 52 | USHORT mUspValue; // 02H-03H value parameters 53 | }; 54 | union { 55 | struct { 56 | UCHAR mUspIndexLow; // 04H index parameter low byte 57 | UCHAR mUspIndexHigh; // 05H index parameter high byte 58 | }; 59 | USHORT mUspIndex; // 04H-05H index parameter 60 | }; 61 | USHORT mLength; // 06H-07H data length 62 | } mUSB_SETUP_PKT, *mPUSB_SETUP_PKT; 63 | 64 | typedef struct _WIN32_COMMAND { // Define the WIN32 command interface structure 65 | union { 66 | ULONG mFunction; // Specify function code or pipe number when inputting 67 | NTSTATUS mStatus; // return operation status when output 68 | }; 69 | ULONG mLength; // access length, return the length of subsequent data 70 | union { 71 | mUSB_SETUP_PKT mSetupPkt; // Data request in the setup phase of USB control transfer 72 | UCHAR mBuffer[512]; // data buffer, the length is 0 to 255B 73 | }; 74 | } mWIN32_COMMAND, *mPWIN32_COMMAND; 75 | // WIN32 Application layer interface command 76 | #define IOCTL_CH341_COMMAND (FILE_DEVICE_UNKNOWN << 16 | FILE_ANY_ACCESS << 14 | 0x0f34 << 2 | METHOD_BUFFERED) // private interface 77 | 78 | #define mWIN32_COMMAND_HEAD mOFFSET(mWIN32_COMMAND, mBuffer) // Header length of WIN32 command interface 79 | 80 | #define mCH341_MAX_NUMBER 32 // Maximum number of CH341/7 connected at the same time 81 | 82 | #define mMAX_BUFFER_LENGTH 0x1000 // The maximum length of the data buffer is 4MB 83 | 84 | #define mMAX_COMMAND_LENGTH (mWIN32_COMMAND_HEAD + mMAX_BUFFER_LENGTH) // maximum data length and the command structure header length 85 | 86 | #define mDEFAULT_BUFFER_LEN 0x0400 // The data buffer default length is 1024 87 | 88 | #define mDEFAULT_COMMAND_LEN (mWIN32_COMMAND_HEAD + mDEFAULT_BUFFER_LEN) // default data length and the command structure header length 89 | 90 | // CH341 endpoint address 91 | #define mCH347_ENDP_DATA_UP 0x86 // The data upload endpoint of CH347 92 | #define mCH347_ENDP_DATA_DOWN 0x06 // The data download endpoint of CH347 93 | 94 | // Pipeline operation command provided by equipment layer interface 95 | #define mPipeDeviceCtrl 0x00000004 // CH347 integrated control pipeline 96 | #define mPipeDataUp 0x00000006 // CH347 data block upload pipeline 97 | #define mPipeDataDown 0x00000007 // CH347 data block download pipeline 98 | 99 | // Function code of application layer interface 100 | #define mFuncNoOperation 0x00000000 // no operation 101 | #define mFuncGetVersion 0x00000001 // Get the driver version number 102 | #define mFuncGetConfig 0x00000002 // Get the USB device configuration descriptor 103 | #define mFuncSetTimeout 0x00000009 // Set USB communication timeout 104 | #define mFuncSetExclusive 0x0000000b // Set exclusive use 105 | #define mFuncResetDevice 0x0000000c // Reset the USB device 106 | #define mFuncResetPipe 0x0000000d // Reset the USB pipe 107 | #define mFuncAbortPipe 0x0000000e // Cancel the data request of the USB pipe 108 | #define mFuncBufferMode 0x00000020 // Set the buffer upload mode and query the data length in the buffer 109 | #define mFuncBufferModeDn 0x00000021 // Set the buffer download mode and query the data length in the buffer 110 | #define mFuncGetVersionEx 0x00000022 // Get the driver version number and chip model 111 | // USB device standard request code 112 | #define mUSB_CLR_FEATURE 0x01 113 | #define mUSB_SET_FEATURE 0x03 114 | #define mUSB_GET_STATUS 0x00 115 | #define mUSB_SET_ADDRESS 0x05 116 | #define mUSB_GET_DESCR 0x06 117 | #define mUSB_SET_DESCR 0x07 118 | #define mUSB_GET_CONFIG 0x08 119 | #define mUSB_SET_CONFIG 0x09 120 | #define mUSB_GET_INTERF 0x0a 121 | #define mUSB_SET_INTERF 0x0b 122 | #define mUSB_SYNC_FRAME 0x0c 123 | 124 | // CH341 manufacturer specific request type for control transmission 125 | #define mCH341_VENDOR_READ 0xC0 // CH341 vendor-specific read operation through control transfer 126 | #define mCH341_VENDOR_WRITE 0x40 // CH341 vendor-specific write operation through control transfer 127 | 128 | #define mCH341A_CMD_I2C_STREAM 0xAA // The command package of the I2C interface, starting from the secondary byte, is the I2C command stream 129 | #define mCH341A_CMD_UIO_STREAM 0xAB // The command package of the UIO interface, starting from the secondary byte, is the command stream 130 | #define mCH341A_CMD_PIO_STREAM 0xAE // The command package of PIO interface, starting from the secondary byte, is the data stream 131 | // CH341A manufacturer specific request code for control transmission 132 | #define mCH341A_BUF_CLEAR 0xB2 // Clear incomplete data 133 | #define mCH341A_I2C_CMD_X 0x54 // Issue the command of I2C interface and execute it immediately 134 | #define mCH341A_DELAY_MS 0x5E // Delay the specified time in microseconds 135 | #define mCH341A_GET_VER 0x5F // Get chip version 136 | 137 | #define mCH341A_CMD_I2C_STM_STA 0x74 // Command flow of I2C interface: generate start bit 138 | #define mCH341A_CMD_I2C_STM_STO 0x75 // Command flow of I2C interface: generate stop bit 139 | #define mCH341A_CMD_I2C_STM_OUT 0x80 // Command flow of I2C interface: output data, bit 5- bit 0 is the length, subsequent bytes are data, and length 0 only sends one byte and returns an answer 140 | #define mCH341A_CMD_I2C_STM_IN 0xC0 // I2C interface command flow: input data, bit 5-bit 0 is the length, and 0 length only receives one byte and sends no response 141 | #define mCH341A_CMD_I2C_STM_MAX (min(0x3F, mCH341_PACKET_LENGTH)) // The maximum length of input and output data of a single command in the command stream of I2C interface 142 | #define mCH341A_CMD_I2C_STM_SET 0x60 // Command flow of I2C interface: set parameters, bit 2=i/o number of SPI (0= single input single output, 1= double input double output), bit 1 0=i2c speed (00= low speed, 01= standard, 10= fast, 11= high speed) 143 | #define mCH341A_CMD_I2C_STM_US 0x40 // Command flow of I2C interface: delay in microseconds, bit 3- bit 0 as delay value 144 | #define mCH341A_CMD_I2C_STM_MS 0x50 // Command flow of I2C interface: delay in microseconds, bit 3-bit 0 as delay value 145 | #define mCH341A_CMD_I2C_STM_DLY 0x0F // Maximum value of single command delay of command flow of I2C interface 146 | #define mCH341A_CMD_I2C_STM_END 0x00 // Command flow of I2C interface: Command package ends in advance 147 | 148 | #define mCH341A_CMD_UIO_STM_IN 0x00 // Command flow of UIO interface: input data D7-D0 149 | #define mCH341A_CMD_UIO_STM_DIR 0x40 // Command flow of UIO interface: set i/o direction D5-D0, bit 5- bit 0 as direction data 150 | #define mCH341A_CMD_UIO_STM_OUT 0x80 // Command flow of UIO interface: output data D5-D0, bit 5-bit 0 is data 151 | #define mCH341A_CMD_UIO_STM_US 0xC0 // Command flow of UIO interface: delay in microseconds, bit 5- bit 0 as delay value 152 | #define mCH341A_CMD_UIO_STM_END 0x20 // Command flow of UIO interface: Command package ends in advance 153 | 154 | #define MAX_DEVICE_PATH_SIZE 128 // Maximum number of characters for device name 155 | #define MAX_DEVICE_ID_SIZE 64 // Maximum number of characters for device ID 156 | #endif _CH341_DLL_H 157 | 158 | // Drive Interface 159 | #define CH347_USB_VENDOR 0 160 | #define CH347_USB_HID 2 161 | #define CH347_USB_VCP 3 162 | 163 | // CH347_USB_VENDOR support CH341/CH347T/CH347F/CH339W 164 | #define CHIP_TYPE_CH341 0 165 | #define CHIP_TYPE_CH347 1 166 | #define CHIP_TYPE_CH347F 2 167 | #define CHIP_TYPE_CH339W 3 168 | #define CHIP_TYPE_CH347T CHIP_TYPE_CH347 169 | 170 | // Chip Function Interface Number 171 | #define CH347_FUNC_UART 0 172 | #define CH347_FUNC_SPI_IIC 1 173 | #define CH347_FUNC_JTAG_IIC 2 174 | #define CH347_FUNC_JTAG_IIC_SPI 3 // CH347F SPI&I2C&JTAG interfaces can be used simultaneously 175 | 176 | #define DEFAULT_READ_TIMEOUT 500 // Default read timeout (mS) 177 | #define DEFAULT_WRITE_TIMEOUT 500 // Default write timeout (mS) 178 | 179 | #define mCH347_PACKET_LENGTH 512 // Length of packets supported by CH347 180 | #pragma pack(1) 181 | // SPI Controller Configuration 182 | typedef struct _SPI_CONFIG { 183 | UCHAR iMode; // 0-3:SPI Mode0/1/2/3 184 | UCHAR iClock; // 0=60MHz, 1=30MHz, 2=15MHz, 3=7.5MHz, 4=3.75MHz, 5=1.875MHz, 6=937.5KHz, 7=468.75KHz 185 | UCHAR iByteOrder; // 0=LSB first(LSB), 1=MSB first(MSB) 186 | USHORT iSpiWriteReadInterval; // The SPI interface routinely reads and writes data command, the unit is uS 187 | UCHAR iSpiOutDefaultData; // SPI MOSI default data when it reads data 188 | ULONG iChipSelect; // Piece of selected control, if bit 7 is 0, CS selection control is ignored, if bit 7 is 1, the parameter is valid: 189 | // Bit 1 Bit 0 is 00/01 and CS1/CS2 pins are selected as low level active chip options respectively 190 | UCHAR CS1Polarity; // Bit 0: CS1 polarity control: 0: effective low level; 1: effective lhigh level; 191 | UCHAR CS2Polarity; // Bit 0: CS2 polarity control: 0: effective low level; 1: effective lhigh level; 192 | USHORT iIsAutoDeativeCS; // Whether to undo CS selection automatically after the operation is complete 193 | USHORT iActiveDelay; // Set the latency for read/write operations after CS selection,the unit is uS 194 | ULONG iDelayDeactive; // Delay time for read and write operations after CS selection is unselected,the unit is uS 195 | } mSpiCfgS, *mPSpiCfgS; 196 | 197 | // Device Information 198 | typedef struct _DEV_INFOR { 199 | UCHAR iIndex; // Current open index 200 | UCHAR DevicePath[MAX_PATH]; // Device link name, used for CreateFile 201 | UCHAR UsbClass; // 0:CH347_USB_CH341, 2:CH347_USB_HID,3:CH347_USB_VCP 202 | UCHAR FuncType; // 0:CH347_FUNC_UART, 1:CH347_FUNC_SPI_I2C, 2:CH347_FUNC_JTAG_I2C 203 | CHAR DeviceID[64]; // USB\VID_xxxx&PID_xxxx 204 | UCHAR ChipMode; // Chip Mode, 0:Mode0(UART0/1); 1:Mode1(Uart1+SPI+I2C); 2:Mode2(HID Uart1+SPI+I2C) 3:Mode3(Uart1+Jtag+I2C) 4:CH347F(Uart*2+Jtag/SPI/I2C) 205 | HANDLE DevHandle; // Device handle 206 | USHORT BulkOutEndpMaxSize; // Upload endpoint size 207 | USHORT BulkInEndpMaxSize; // downstream endpoint size 208 | UCHAR UsbSpeedType; // USB Speed type, 0:FS,1:HS,2:SS 209 | UCHAR CH347IfNum; // USB interface number: CH347T: IF0:UART; IF1:SPI/IIC/JTAG/GPIO 210 | // CH347F: IF0:UART0; IF1:UART1; IF2:SPI/IIC/JTAG/GPIO 211 | UCHAR DataUpEndp; // The endpoint address 212 | UCHAR DataDnEndp; // The endpoint address 213 | CHAR ProductString[64]; // Product string in USB descriptor 214 | CHAR ManufacturerString[64]; // Manufacturer string in USB descriptor 215 | ULONG WriteTimeout; // USB write timeout 216 | ULONG ReadTimeout; // USB read timeout 217 | CHAR FuncDescStr[64]; // Interface functions 218 | UCHAR FirewareVer; // Firmware version 219 | 220 | } mDeviceInforS, *mPDeviceInforS; 221 | #pragma pack() 222 | 223 | // CH347 Mode Common Function,support open,close,USB read,USB written and HID of all modes. 224 | // Open USB device 225 | HANDLE WINAPI CH347OpenDevice(ULONG DevI); // Specifies the device number 226 | 227 | // Close USB device 228 | BOOL WINAPI CH347CloseDevice(ULONG iIndex); // Specifies the device number 229 | 230 | // Get the USB serial number of the device 231 | BOOL WINAPI CH347GetSerialNumber(ULONG iIndex, // Specifies the device number 232 | PUCHAR iSerialNumberStr); // Point to the obtained device serial number 233 | 234 | // Get Device Information 235 | BOOL WINAPI CH347GetDeviceInfor(ULONG iIndex, mDeviceInforS *DevInformation); 236 | 237 | // Get CH347 type:0:CHIP_TYPE_CH341,1:CHIP_TYPE_CH347/CHIP_TYPE_CH347T,2:CHIP_TYPE_CH347F,3:CHIP_TYPE_CH339W 238 | UCHAR WINAPI CH347GetChipType(ULONG iIndex); 239 | 240 | // Obtain driver version, library version, device version and chip type(CH341(FS)/CH347HS) 241 | BOOL WINAPI CH347GetVersion(ULONG iIndex, 242 | PUCHAR iDriverVer, 243 | PUCHAR iDLLVer, 244 | PUCHAR ibcdDevice, 245 | PUCHAR iChipType); // CHIP_TYPE_CH341/7 246 | 247 | typedef VOID(CALLBACK *mPCH347_NOTIFY_ROUTINE)( // Device event notification callback routine 248 | ULONG iEventStatus); // Device event and current status (refer to the description below): 0=Device unplug event, 3=Device insertion event 249 | 250 | #define CH347_DEVICE_ARRIVAL 3 // Device insertion event,has been inserted 251 | #define CH347_DEVICE_REMOVE_PEND 1 // Device wil be unplugged 252 | #define CH347_DEVICE_REMOVE 0 // Device unplug event,has been pulled out 253 | 254 | BOOL WINAPI CH347SetDeviceNotify( // Configure device event notifier 255 | ULONG iIndex, // Specifies the device number,bit 0 corresponds to the first device 256 | PCHAR iDeviceID, // Optional parameter,pointing to a string terminated by \0,specifying the ID of the monitored device 257 | mPCH347_NOTIFY_ROUTINE iNotifyRoutine); // Specifies the port device event callback program. If it is NULL, the event notification will be canceled. Otherwise, the program will be called when an event is detected. 258 | 259 | // Read USB data block 260 | BOOL WINAPI CH347ReadData(ULONG iIndex, // Specifies the device number 261 | PVOID oBuffer, // Points to a buffer large enough to save the read data 262 | PULONG ioLength); // Points to the length unit, the length to be read when input is the length to be read, and the actual read length after return 263 | 264 | // Write USB data block 265 | BOOL WINAPI CH347WriteData(ULONG iIndex, // Specifies the device number 266 | PVOID iBuffer, // Points to a buffer large enough to save the written data 267 | PULONG ioLength); // Points to the length unit,the input length is the intended length, and the return length is the actual length 268 | 269 | // Set the timeout of USB data read and write 270 | BOOL WINAPI CH347SetTimeout(ULONG iIndex, // Specifies the device number 271 | ULONG iWriteTimeout, // Specifies the timeout for USB to write data blocks, in milliseconds mS,0xFFFFFFFF specifies no timeout (default) 272 | ULONG iReadTimeout); // Specifies the timeout for USB to read data blocks, in milliseconds mS,0xFFFFFFFF specifies no timeout (default) 273 | 274 | /***************SPI********************/ 275 | // SPI Controller Initialization 276 | BOOL WINAPI CH347SPI_Init(ULONG iIndex, mSpiCfgS *SpiCfg); 277 | 278 | // Set the SPI clock frequency, and after calling this interface, you need to call CH347SPI_Init again for reinitialisation. 279 | BOOL WINAPI CH347SPI_SetFrequency(ULONG iIndex, // Specify device number 280 | ULONG iSpiSpeedHz);// Set the SPI clock, with the unit in Hz. 281 | 282 | // CH347F set the SPI databit 283 | BOOL WINAPI CH347SPI_SetDataBits(ULONG iIndex, // Specify device number 284 | UCHAR iDataBits); // 0=8bit,1=16bit 285 | 286 | // Get SPI controller configuration information 287 | BOOL WINAPI CH347SPI_GetCfg(ULONG iIndex, mSpiCfgS *SpiCfg); 288 | 289 | // Before setting the chip selection status, call CH347SPI_Init to set CS 290 | BOOL WINAPI CH347SPI_ChangeCS(ULONG iIndex, // Specify device number 291 | UCHAR iStatus); // 0=Cancel the piece to choose,1=Set piece selected 292 | 293 | // Set SPI slice selection 294 | BOOL WINAPI CH347SPI_SetChipSelect(ULONG iIndex, // Specify device number 295 | USHORT iEnableSelect, // The lower octet is CS1 and the higher octet is CS2. A byte value of 1= sets CS, 0= ignores this CS setting 296 | USHORT iChipSelect, // The lower octet is CS1 and the higher octet is CS2. A byte value of 1= sets CS, 0= ignores this CS setting 297 | ULONG iIsAutoDeativeCS, // The lower 16 bits are CS1 and the higher 16 bits are CS2. Whether to undo slice selection automatically after the operation is complete 298 | ULONG iActiveDelay, // The lower 16 bits are CS1 and the higher 16 bits are CS2. Set the latency of read/write operations after chip selection, the unit is us 299 | ULONG iDelayDeactive); // The lower 16 bits are CS1 and the higher 16 bits are CS2. Delay time for read and write operations after slice selection the unit is us 300 | 301 | // SPI4 write data 302 | BOOL WINAPI CH347SPI_Write(ULONG iIndex, // Specify device number 303 | ULONG iChipSelect, // CS selection control, when bit 7 is 0, slice selection control is ignored, and when bit 7 is 1, slice selection operation is performed 304 | ULONG iLength, // Number of bytes of data to be transferred 305 | ULONG iWriteStep, // The length of a single block to be read 306 | PVOID ioBuffer); // Point to a buffer to place the data to be written out from MOSI 307 | 308 | // SPI4 read data, no need to write data first, much more efficient than CH347SPI_WriteRead 309 | BOOL WINAPI CH347SPI_Read(ULONG iIndex, // Specify device number 310 | ULONG iChipSelect, // Slice selection control, when bit 7 is 0, slice selection control is ignored, and when bit 7 is 1, slice selection operation is performed 311 | ULONG oLength, // Number of bytes to send 312 | PULONG iLength, // Number of bytes of data to be read in 313 | PVOID ioBuffer); // Points to a buffer that place the data to be written out from DOUT, return the data read in from DIN 314 | 315 | // Handle SPI data stream 4-wire interface 316 | BOOL WINAPI CH347SPI_WriteRead(ULONG iIndex, // Specify the device number 317 | ULONG iChipSelect, // Selection control, if the film selection control bit 7 is 0, ignore the film selection control bit 7 is 1 and operate the film selection 318 | ULONG iLength, // Number of bytes of data to be transferred 319 | PVOID ioBuffer); // Points to a buffer that place the data to be written out from DOUT, return the data read in from DIN 320 | 321 | // place the data to be written from MOSI, return the data read in from MISO 322 | BOOL WINAPI CH347StreamSPI4(ULONG iIndex, // Specify the device number 323 | ULONG iChipSelect, // Film selection control, if bit 7 is 0, slice selection control is ignored.If bit 7 is 1, the parameter is valid:Bit 1 bit 0 is 00/01/10. Select D0/D1/D2 pins as low level active chip options respectively 324 | ULONG iLength, // Number of bytes of data to be transferred 325 | PVOID ioBuffer); // Points to a buffer, places data to be written out from DOUT, and returns data to be read in from DIN 326 | 327 | /***************JTAG********************/ 328 | // JTAG interface initialization, set mode and speed 329 | BOOL WINAPI CH347Jtag_INIT(ULONG iIndex, 330 | UCHAR iClockRate); // Communication speed; The value ranges from 0 to 5. A larger value indicates a faster communication speed 331 | 332 | // Gets Jtag speed configuration 333 | BOOL WINAPI CH347Jtag_GetCfg(ULONG iIndex, // Specify the device number 334 | UCHAR *ClockRate); // Communication speed; The value ranges from 0 to 5. A larger value indicates a faster communication speed 335 | 336 | // Function that performs state switching by changing the value of TMS 337 | BOOL WINAPI CH347Jtag_TmsChange(ULONG iIndex, // Specify the device number 338 | PUCHAR tmsValue, // The TMS values that need to be switched form one byte of data in the switching order 339 | ULONG Step, // The number of bit values that need to be read from the tmsValue value 340 | ULONG Skip); // Count from the skip bit of tmsValue to step 341 | 342 | // Read/write data in the shift-dr/ir state and Exit DR/IR after the command is executed 343 | // State machine :Shift-DR/ ir.rw.->Exit DR/IR 344 | BOOL WINAPI CH347Jtag_IoScan(ULONG iIndex, 345 | PUCHAR DataBits, // Bits of data that need to be transferred 346 | ULONG DataBitsNb, // The number of bits of data to be transmitted 347 | BOOL IsRead); // Whether to read data 348 | 349 | // Switch to the shift-dr/ir state for reading/writing. After the command is executed, if the last packet is displayed, switch to Exit DR/IR. If not, stop at Shift-DR/IR 350 | // State machine :Shift-DR/IR.RW.. ->[Exit DR/IR] 351 | BOOL WINAPI CH347Jtag_IoScanT(ULONG iIndex, // Specify the device number 352 | PUCHAR DataBits, // Bits of data that need to be transferred 353 | ULONG DataBitsNb, // The number of bits of data to be transmitted 354 | BOOL IsRead, // Whether to read data 355 | BOOL IsLastPkt); // Whether to the last packet 356 | 357 | // Reset the Tap status function. The TMS is high for more than six clocks, Tap state on Test-Logic Reset 358 | ULONG WINAPI CH347Jtag_Reset(ULONG iIndex); 359 | 360 | // Perform TRST operations to reset hardware 361 | BOOL WINAPI CH347Jtag_ResetTrst(ULONG iIndex, // Specify the device number 362 | BOOL iLevel); // 0=Set lower,1=Set High 363 | 364 | // Bit band mode JTAG IR/DR data read and write. Suitable for reading and writing small amounts of data. Such as command operation, state machine switching and other control transmission. For batch data transmission, you are advised to use CH347Jtag_WriteRead_Fast 365 | // Command packages are read and written in batches in 4096 bytes 366 | // The state machine: Run-Test->Shift-IR/DR..->Exit IR/DR -> Run-Test 367 | BOOL WINAPI CH347Jtag_WriteRead(ULONG iIndex, // Specify the device number 368 | BOOL IsDR, // =TRUE: DR data read/write, =FALSE:IR data read/write 369 | ULONG iWriteBitLength, // Write length, the length to be written 370 | PVOID iWriteBitBuffer, // Points to a buffer to place data ready to be written out 371 | PULONG oReadBitLength, // Points to the length unit and returns the length actually read 372 | PVOID oReadBitBuffer); // Points to a buffer large enough to hold the read data 373 | 374 | // JTAG IR/DR data batch read and write The IR/DR data is used for multi-byte continuous read and write. For example, download firmware. The hardware has four buffers. If the buffer is written before the buffer is read, the length cannot exceed 4096 bytes. Buffer size can be adjusted 375 | // The state machine: Run-Test->Shift-IR/DR..->Exit IR/DR -> Run-Test 376 | BOOL WINAPI CH347Jtag_WriteRead_Fast(ULONG iIndex, // Specify the device number 377 | BOOL IsDR, // =TRUE: in SHIFT-DR read/write, =FALSE:IR data read/write 378 | ULONG iWriteBitLength, // Write length. The length to be written 379 | PVOID iWriteBitBuffer, // Points to a buffer to place data ready to be written out 380 | PULONG oReadBitLength, // Point to the length unit and return the actual read length 381 | PVOID oReadBitBuffer); // Points to a buffer large enough to hold the read data 382 | 383 | // Bitband mode JTAG IR/DR Data read and write. It is suitable for reading and writing small amounts of data. Such as instruction operation, state machine switching and other control class transmission. For batch data transfer, CH347Jtag_WriteRead_Fast is recommended 384 | // State switch:Run-Test-> Shift-IR/DR..->Exit IR/DR -> Run-Test 385 | BOOL WINAPI CH347Jtag_WriteReadEx(ULONG iIndex, // Specify the device number 386 | BOOL IsInDrOrIr, // =TRUE: In SHIFT-DR read/write ==FALSE: Run-Test->Shift-IR/DR.(data read/write).->Exit IR/DR -> Run-Test 387 | BOOL IsDR, // =TRUE: in SHIFT-DR read/write, =FALSE:IR data read/write 388 | ULONG iWriteBitLength, // Write length. The length to be written 389 | PVOID iWriteBitBuffer, // Points to a buffer to place data ready to be written out 390 | PULONG oReadBitLength, // Point to the length unit and return the actual read length 391 | PVOID oReadBitBuffer); // 392 | 393 | // JTAG IR/DR Read and write data in batches. It is used to read and write multi-byte data continuously. For example, download JTAG firmware. Because the hardware has 4K buffer, such as write before read, the length does not exceed 4096 bytes. The buffer size can be adjusted 394 | // State switch:Run-Test->Shift-IR/DR..->Exit IR/DR -> Run-Test 395 | BOOL WINAPI CH347Jtag_WriteRead_FastEx(ULONG iIndex, // Specify the device number 396 | BOOL IsInDrOrIr, // =TRUE: In SHIFT-DR read/write ==FALSE: Run-Test->Shift-IR/DR.(data read/write).->Exit IR/DR -> Run-Test 397 | BOOL IsDR, // =TRUE: in SHIFT-DR read/write, =FALSE:IR data read/write 398 | ULONG iWriteBitLength, // Write length. The length to be written 399 | PVOID iWriteBitBuffer, // Points to a buffer to place data ready to be written out 400 | PULONG oReadBitLength, // Point to the length unit and return the actual read length 401 | PVOID oReadBitBuffer); // Points to a buffer large enough to hold the read data 402 | 403 | // Single-step switching of the JTAG state machine must be executed in order. 404 | BOOL WINAPI CH347Jtag_SwitchTapState(UCHAR TapState); // state to switch 405 | // 0:Test-Logic Reset,1:Run-Test/Idle,2:Run-Test/Idle -> Shift-DR,3:Shift-DR -> Run-Test/Idle 406 | // 4:Run-Test/Idle -> Shift-IR, 5:Shift-IR -> Run-Test/Idle, 6:Exit1-DR/IR -> Update-DR/IR -> Run-Test/Idle 407 | 408 | // Single-step switching of the JTAG state machine allows for the specification of the operating device iIndex. 409 | BOOL WINAPI CH347Jtag_SwitchTapStateEx(ULONG iIndex, // Specify the device number 410 | UCHAR TapState); // state to switch 411 | 412 | // JTAG DR Write, in bytes, for multi-byte sequential reads and writes. For example, download firmware. 413 | // The state machine: Run-Test->Shift-DR..->Exit DR -> Run-Test 414 | BOOL WINAPI CH347Jtag_ByteWriteDR(ULONG iIndex, // Specify the device number 415 | ULONG iWriteLength, // Write length, length of bytes to be written 416 | PVOID iWriteBuffer); // Points to a buffer to place data ready to be written out 417 | 418 | // JTAG DR Read, read multiple bytes consecutively in bytes. 419 | // The state machine: Run-Test->Shift-DR..->Exit DR -> Run-Test 420 | BOOL WINAPI CH347Jtag_ByteReadDR(ULONG iIndex, // Specify the device number 421 | PULONG oReadLength, // Points to the length unit and returns the length of the bytes actually read 422 | PVOID oReadBuffer); // Points to a buffer large enough to hold the read data 423 | 424 | // JTAG IR write, written in bytes, multiple bytes are written consecutively. 425 | // The state machine: Run-Test->Shift-IR..->Exit IR -> Run-Test 426 | BOOL WINAPI CH347Jtag_ByteWriteIR(ULONG iIndex, // Specify the CH347 device number 427 | ULONG iWriteLength, // Write length, the length of bytes to be written 428 | PVOID iWriteBuffer); // Points to a buffer to place data ready to be written out 429 | 430 | // JTAG IR read, readen in bytes, multiple bytes are readen consecutively. 431 | // The state machine: Run-Test->Shift-IR..->Exit IR -> Run-Test 432 | BOOL WINAPI CH347Jtag_ByteReadIR(ULONG iIndex, // Specify the device number 433 | PULONG oReadLength, // Points to the length unit and returns the length of the bytes actually read 434 | PVOID oReadBuffer); // Points to a buffer large enough to hold the read data 435 | 436 | // Bit band mode JTAG DR data write. Suitable for reading and writing small amounts of data. Such as command operation, state machine switching and other control transmission. For batch data transmission, CH347Jtag_ByteWriteDR is recommended 437 | // The state machine: Run-Test->Shift-DR..->Exit DR -> Run-Test 438 | BOOL WINAPI CH347Jtag_BitWriteDR(ULONG iIndex, // Specify the device number 439 | ULONG iWriteBitLength, // Points to the length unit and returns the length of the bytes actually read 440 | PVOID iWriteBitBuffer); // Points to a buffer large enough to hold the read data 441 | 442 | // Bit band mode JTAG IR data write. Suitable for reading and writing small amounts of data. Such as command operation, state machine switching and other control transmission. For batch data transmission, CH347Jtag_ByteWriteIR is recommended 443 | // The state machine: Run-Test->Shift-IR..->Exit IR -> Run-Test 444 | BOOL WINAPI CH347Jtag_BitWriteIR(ULONG iIndex, // Specify the device number 445 | ULONG iWriteBitLength, // Points to the length unit and returns the length of the bytes actually read 446 | PVOID iWriteBitBuffer); // Points to a buffer large enough to hold the read data 447 | 448 | // Bit band mode JTAG IR data read. Suitable for reading and writing small amounts of data. Such as command operation, state machine switching, etc. For batch data transmission, CH347Jtag_ByteReadIR is recommended. 449 | // The state machine: Run-Test->Shift-IR..->Exit IR -> Run-Test 450 | BOOL WINAPI CH347Jtag_BitReadIR(ULONG iIndex, // Specify the device number 451 | PULONG oReadBitLength, // Points to the length unit and returns the length of the bytes actually read 452 | PVOID oReadBitBuffer); // Points to a buffer large enough to hold the read data 453 | 454 | // Bit band mode JTAG DR data read. Suitable for reading and writing small amounts of data. For batch and high-speed data transmission, CH347Jtag_ByteReadDR is recommended 455 | // The state machine: Run-Test->Shift-DR..->Exit DR -> Run-Test 456 | BOOL WINAPI CH347Jtag_BitReadDR(ULONG iIndex, // Specify the device number 457 | PULONG oReadBitLength, // Points to the length unit and returns the length of the bytes actually read 458 | PVOID oReadBitBuffer); // Points to a buffer large enough to hold the read data 459 | 460 | /***************GPIO********************/ 461 | // Get the GPIO direction and pin level of CH347 462 | BOOL WINAPI CH347GPIO_Get(ULONG iIndex, 463 | UCHAR *iDir, // Pin direction: GPIo0-7 corresponding bit 0-7,0: input; 1: output 464 | UCHAR *iData); // GPIO0 level: GPIO0-7 corresponding bit 0-7,0: low level; 1: high level 465 | 466 | // Set the GPIO direction and pin level of CH347 467 | BOOL WINAPI CH347GPIO_Set(ULONG iIndex, 468 | UCHAR iEnable, // Data validity flag: The corresponding bits 0-7 correspond to GPIO0-7. 469 | UCHAR iSetDirOut, // Sets the I/O direction, with pin 0 corresponding to input and pin 1 corresponding to output. Gpio0-7 corresponds to bits 0-7. 470 | UCHAR iSetDataOut); // Outputs data. If the I/O direction is output, then a pin outputs low level at a clear 0 and high level at a position 1 471 | 472 | typedef VOID(CALLBACK *mPCH347_INT_ROUTINE)( // Interrupt service routine 473 | PUCHAR iStatus); // For interrupt status data, refer to the bit description below 474 | // 8 byte GPIO0-7 pin status, the bits per byte are defined as follows. 475 | // Bit7:Current GPIO0 direction, 0:Input; 1:Output 476 | // Bit6:Current GPIO0 level, 0:Low level;1:High level 477 | // Bit5:Whether the current GPIO0 is set to interrupt; 0:Query mode; 1:Interrupt mode 478 | // Bit4-3:Set the GPIO0 interrupt mode, 00:Falling edge trigger; 01:Rising edge trigger; 10:Double edge trigger;11: reserved; 479 | // Bit2-0:reserved; 480 | 481 | // Set GPIO interrupt service routine 482 | BOOL WINAPI CH347SetIntRoutine(ULONG iIndex, // Specify the device number 483 | UCHAR Int0PinN, // INT0 GPIO pin number greater than 7: Disable this interrupt source. 0-7 corresponds to gpio0-7 484 | UCHAR Int0TripMode, // INT0 type: 00:Falling edge trigger; 01:Rising edge trigger; 02:Double edge trigger; 03:reserve; 485 | UCHAR Int1PinN, // INT1 GPIO pin number. If it is greater than 7, this interrupt source is not enabled. 0-7 corresponds to gpio0-7 486 | UCHAR Int1TripMode, // INT1 type: 00:Falling edge trigger; 01:Rising edge trigger; 02:Double edge trigger; 03:reserve; 487 | mPCH347_INT_ROUTINE iIntRoutine); // Specifies the interrupt service program. If NULL is specified, the interrupt service is canceled. Otherwise, the program is invoked when the interrupt is performed 488 | 489 | // Read interrupt data 490 | BOOL WINAPI CH347ReadInter(ULONG iIndex, // Specify the device number 491 | PUCHAR iStatus); // Refers to the 8-byte unit used to hold read GPIO pin state data, refer to the bit instructions below 492 | 493 | // Abandon interrupt data read operation 494 | BOOL WINAPI CH347AbortInter(ULONG iIndex); // Specify the device number 495 | 496 | // Enter the IAP firmware upgrade mode 497 | BOOL WINAPI CH347StartIapFwUpate(ULONG iIndex, 498 | ULONG FwSize); // The length of the firmware 499 | 500 | /**************HID/VCP Serial Port*********************/ 501 | // Open serial port 502 | HANDLE WINAPI CH347Uart_Open(ULONG iIndex); 503 | 504 | // Close serial port 505 | BOOL WINAPI CH347Uart_Close(ULONG iIndex); 506 | 507 | // Set the device event notification program 508 | BOOL WINAPI CH347Uart_SetDeviceNotify( 509 | ULONG iIndex, // Specify the device number, 0 corresponds to the first device 510 | PCHAR iDeviceID, // Optional parameter,points to a string specifying the ID of the device to be monitored, terminated with \0 511 | mPCH347_NOTIFY_ROUTINE iNotifyRoutine); // Specifies the device event callback. NULL cancels event notification, otherwise it will be called when an event is detected 512 | 513 | // Obtain UART hardware configuration 514 | BOOL WINAPI CH347Uart_GetCfg(ULONG iIndex, // Specify the device number 515 | PULONG BaudRate, // Baud rate 516 | PUCHAR ByteSize, // Data bits (5,6,7,8,16) 517 | PUCHAR Parity, // Parity bits(0:None; 1:Odd; 2:Even; 3:Mark; 4:Space) 518 | PUCHAR StopBits, // Stop bits (0:1 stop bits; 1:1.5 stop bit; 2:2 stop bit); 519 | PUCHAR ByteTimeout); // Byte timeout 520 | 521 | // Set UART configuration 522 | BOOL WINAPI CH347Uart_Init(ULONG iIndex, // Specify the device number 523 | DWORD BaudRate, // Baud rate 524 | UCHAR ByteSize, // Data bits (5,6,7,8,16) 525 | UCHAR Parity, // Check bit (0:None; 1:Odd; 2:Even; 3:Mark; 4:Space) 526 | UCHAR StopBits, // Stop bits 0:1 Stop bit; 1:1.5 stop bit; 2:2 stop bit); 527 | UCHAR ByteTimeout); // Byte Timeout duration, in unit of 100uS 528 | 529 | // Set the timeout of USB data read and write 530 | BOOL WINAPI CH347Uart_SetTimeout(ULONG iIndex, // Specify the device number 531 | ULONG iWriteTimeout, // Specifies the timeout for USB to write data blocks, in milliseconds mS,0xFFFFFFFF specifies no timeout (default) 532 | ULONG iReadTimeout); // Specifies the timeout for USB to read data blocks, in milliseconds mS,0xFFFFFFFF specifies no timeout (default) 533 | 534 | // Read data block 535 | BOOL WINAPI CH347Uart_Read(ULONG iIndex, // Specify the device number 536 | PVOID oBuffer, // Points to a buffer large enough to hold the read data 537 | PULONG ioLength); // Refers to the length unit. The input is the length to be read and the return is the actual length to be read 538 | 539 | // Write out blocks of data 540 | BOOL WINAPI CH347Uart_Write(ULONG iIndex, // Specify the device number 541 | PVOID iBuffer, // Points to a buffer to place data ready to be written out 542 | PULONG ioLength); // Point to the length unit. The input is the intended length and the return is the actual length 543 | 544 | // Query how many bytes are unfetched in the read buffer 545 | BOOL WINAPI CH347Uart_QueryBufUpload(ULONG iIndex, // Specify the device number 546 | LONGLONG *RemainBytes); 547 | 548 | // Obtaining Device Information 549 | BOOL WINAPI CH347Uart_GetDeviceInfor(ULONG iIndex, mDeviceInforS *DevInformation); 550 | 551 | /********I2C***********/ 552 | // Set the serial port flow mode 553 | BOOL WINAPI CH347I2C_Set(ULONG iIndex, // Specify the device number 554 | ULONG iMode); // See downlink for the specified mode 555 | // bit 1-bit 0: I2C interface speed /SCL frequency, 00= low speed /20KHz,01= standard /100KHz(default),10= fast /400KHz,11= high speed /750KHz 556 | // Other reservations, must be 0 557 | 558 | // Set I2C Clock Stretch 559 | BOOL WINAPI CH347I2C_SetStretch(ULONG iIndex, // Specify the device number 560 | BOOL iEnable); // I2C Clock Stretch enable, 1:enable,0:disable 561 | 562 | // Set the hardware asynchronous delay to a specified number of milliseconds before the next stream operation 563 | BOOL WINAPI CH347I2C_SetDelaymS(ULONG iIndex, // Specify the device number 564 | ULONG iDelay); // Specifies the delay duration (mS) 565 | 566 | // Set the I2C pins drive mode. 567 | BOOL WINAPI CH347I2C_SetDriverMode(ULONG iIndex, // Specify the device number 568 | UCHAR iMode); // 0=open-drain mode; 1=push-pull mode 569 | 570 | // Process I2C data stream, 2-wire interface, clock line for SCL pin, data line for SDA pin 571 | BOOL WINAPI CH347StreamI2C(ULONG iIndex, // Specify the device number 572 | ULONG iWriteLength, // The number of bytes of data to write 573 | PVOID iWriteBuffer, // Points to a buffer to place data ready to be written out, the first byte is usually the I2C device address and read/write direction bit 574 | ULONG iReadLength, // Number of bytes of data to be read 575 | PVOID oReadBuffer); // Points to a buffer to place data ready to be read in 576 | 577 | // Process I2C data stream, 2-wire interface, SCL pin for clock line, SDA pin for data line (quasi-bidirectional I/O), speed of about 56K bytes, and return the number of ACK obtained by the host side 578 | BOOL WINAPI CH347StreamI2C_RetACK(ULONG iIndex, // Specify the device number 579 | ULONG iWriteLength, // The number of bytes of data to write 580 | PVOID iWriteBuffer, // Points to a buffer to place data ready to be written out, the first byte is usually the I2C device address and read/write direction bit 581 | ULONG iReadLength, // Number of bytes of data to be read 582 | PVOID oReadBuffer, // Points to a buffer to place data ready to be read in 583 | PULONG rAckCount); // Refers to the ACK value returned by read/write 584 | 585 | #ifndef _CH341_DLL_H 586 | typedef enum _EEPROM_TYPE { // EEPROM type 587 | ID_24C01, 588 | ID_24C02, 589 | ID_24C04, 590 | ID_24C08, 591 | ID_24C16, 592 | ID_24C32, 593 | ID_24C64, 594 | ID_24C128, 595 | ID_24C256, 596 | ID_24C512, 597 | ID_24C1024, 598 | ID_24C2048, 599 | ID_24C4096 600 | } EEPROM_TYPE; 601 | #endif 602 | 603 | // Reads data blocks from EEPROM at a speed of about 56 KB 604 | BOOL WINAPI CH347ReadEEPROM(ULONG iIndex, // Specify the device number 605 | EEPROM_TYPE iEepromID, // Specifies the EEPROM model 606 | ULONG iAddr, // Specifies the address of data unit 607 | ULONG iLength, // Number of bytes of data to be read 608 | PUCHAR oBuffer); // Points to a buffer to place data ready to be read in 609 | 610 | // Writes a data block to the EEPROM 611 | BOOL WINAPI CH347WriteEEPROM(ULONG iIndex, // Specify the device number 612 | EEPROM_TYPE iEepromID, // Specifies the EEPROM model 613 | ULONG iAddr, // Specifies the address of data unit 614 | ULONG iLength, // Number of bytes of data to be written out 615 | PUCHAR iBuffer); // Points to a buffer to place data ready to be written out 616 | 617 | // Set the low cycle delay time for the 8th clock, applicable only to CH347T. 618 | BOOL WINAPI CH347I2C_SetAckClk_DelayuS(ULONG iIndex, // Specify the device number 619 | ULONG iDelay); // Specified delay in microseconds. 620 | 621 | // This function is used to query the current enable status of each interface function of the CH339W chip with the specified index. 622 | // Return value bit definition: 623 | // Bit 7 (0x80): USB to JTAG enable status (1 = enabled, 0 = disabled) 624 | // Bit 6 (0x40): USB to SPI enable status (1 = enabled, 0 = disabled) 625 | // Bit 5 (0x20): USB to UART enable (without flow control) (1 = enabled, 0 = disabled) 626 | // Bit 4 (0x10): USB to UART flow control enable (1 = enabled, 0 = disabled) 627 | // Bit 3 (0x08): USB to I2C enable status (1 = enabled, 0 = disabled) 628 | // Bits 2 - 0: Reserved bits 629 | UCHAR WINAPI CH339GetChipFuncState( ULONG iIndex ); // Specify the device number 630 | 631 | #ifdef __cplusplus 632 | } 633 | #endif 634 | 635 | #endif // _CH347_DLL_H 636 | --------------------------------------------------------------------------------