├── ch341-gpio.png ├── CH341PAR_LINUX.ZIP ├── ch341-parport-mem.png ├── CH341PAR_LINUX ├── demo │ ├── Makefile │ ├── flash.h │ ├── Makefile2 │ ├── flash_sst.h │ ├── ch34x_lib.h │ ├── ch34x_demo.c │ ├── ch34x_lib.c │ └── ch34x_demo_gui.c ├── driver │ ├── Makefile │ └── ch34x_pis.c └── lib │ ├── ch34x_lib.h │ └── ch34x_lib.c └── README.md /ch341-gpio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoobab/ch341-parport/HEAD/ch341-gpio.png -------------------------------------------------------------------------------- /CH341PAR_LINUX.ZIP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoobab/ch341-parport/HEAD/CH341PAR_LINUX.ZIP -------------------------------------------------------------------------------- /ch341-parport-mem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoobab/ch341-parport/HEAD/ch341-parport-mem.png -------------------------------------------------------------------------------- /CH341PAR_LINUX/demo/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for WCH CH34x chips 2 | 3 | CC := gcc 4 | OBJ := DEMO 5 | CFLAGS := -Wall -g 6 | OBJ_C := ch34x_demo.o ch34x_lib.o 7 | 8 | $(OBJ):$(OBJ_C) 9 | $(CC) -o $@ $^ $(CFLAGS) 10 | $(CC) -c ch34x_lib.c $(CFLAGS) 11 | %.o:%.c 12 | $(CC) -c $< $(CFLAGS) 13 | 14 | clean: 15 | rm -rf *.o $(OBJ) 16 | 17 | -------------------------------------------------------------------------------- /CH341PAR_LINUX/driver/Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(KERNELRELEASE), ) 2 | KERNELDIR := /lib/modules/$(shell uname -r)/build 3 | PWD :=$(shell pwd) 4 | default: 5 | $(MAKE) -C $(KERNELDIR) M=$(PWD) 6 | clean: 7 | rm -rf .tmp_versions Module.symvers *.mod.c *.o *.ko .*.cmd Module.markers modules.order 8 | load: 9 | modprobe usbserial 10 | insmod ch34x_pis.ko 11 | unload: 12 | rmmod ch34x_pis 13 | else 14 | obj-m := ch34x_pis.o 15 | endif 16 | -------------------------------------------------------------------------------- /CH341PAR_LINUX/demo/flash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * flash.h 3 | * 4 | * Created on: Dec 2, 2013 5 | * Author: root 6 | */ 7 | 8 | #ifndef FLASH_H_ 9 | #define FLASH_H_ 10 | 11 | #define ReadByte 0x03 12 | #define Sector_Erase 0x20 13 | #define Block_Erase 0x52 14 | #define Chip_Erase 0x60 15 | #define Byte_Program 0x02 16 | #define AAI 0xAF 17 | #define RDSR 0x05 18 | #define EWSR 0x50 19 | #define WRSR 0x01 20 | #define WREN 0x06 21 | #define WRDI 0x04 22 | #define ReadID 0x90 23 | 24 | #endif /* FLASH_H_ */ 25 | -------------------------------------------------------------------------------- /CH341PAR_LINUX/demo/Makefile2: -------------------------------------------------------------------------------- 1 | # Makefile for WCH CH34x chips 2 | 3 | CC := gcc 4 | OBJ := DEMO 5 | OBJ_GTK := DEMO_GUI 6 | CFLAGS := -Wall -g 7 | CFLAGS_GUI := -Wall -g `pkg-config --cflags --libs gtk+-2.0` 8 | OBJ_C := ch34x_demo.o ch34x_lib.o 9 | OBJ_C_GUI := ch34x_demo_gui.o ch34x_lib.o 10 | 11 | 12 | $(OBJ):$(OBJ_C) 13 | $(CC) -o $@ $^ $(CFLAGS) 14 | $(CC) -c ch34x_lib.c $(CFLAGS) 15 | $(CC) -c ch34x_demo_gui.c $(CFLAGS_GUI) 16 | $(CC) -o $(OBJ_GTK) $(OBJ_C_GUI) $(CFLAGS_GUI) 17 | %.o:%.c 18 | $(CC) -c $< $(CFLAGS) 19 | 20 | #DEMO:$(OBJ_C) 21 | # $(CC) -o $@ $(OBJ_C) $(CFLAGS) 22 | clean: 23 | rm -rf *.o $(OBJ) $(OBJ_GTK) 24 | -------------------------------------------------------------------------------- /CH341PAR_LINUX/demo/flash_sst.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | //**************************************** 4 | // 5 | //** Copyright (C) W.ch 2013 ** 6 | // 7 | //** Web: http://www.wch.cn ** 8 | // 9 | //**************************************** 10 | // 11 | //** LIB for USB interface chip CH341 ** 12 | // 13 | //** C, LINUX ** 14 | // 15 | //**************************************** 16 | // 17 | // 18 | 19 | #ifndef _FLASH_SST_H 20 | #define _FLASH_SST_H 21 | 22 | #define ReadByte 0x03 23 | #define Sector_Erase 0x20 24 | #define Block_Erase 0x52 25 | #define Chip_Erase 0x60 26 | #define Byte_Program 0x02 27 | #define AAI 0xAF 28 | #define RDSR 0x05 29 | #define EWSR 0x50 30 | #define WRSR 0x01 31 | #define WREN 0x06 32 | #define WRDI 0x04 33 | #define ReadID 0x90 34 | 35 | int ReadFlashId(); 36 | 37 | BOOL CH34xWriteEnable(); 38 | 39 | BOOL CH34xSectorErase( ULONG StartAddr ); 40 | 41 | int CH34x_Flash_ReadByte( PVOID oBuffer, 42 | ULONG iAddr); 43 | 44 | int CH34x_Flash_ReadBlock( PVOID oBuffer, 45 | ULONG iAddr); 46 | 47 | BOOL CH34xFlash_Wait(); 48 | 49 | BOOL CH34x_Flash_Write( PVOID iBuffer, 50 | ULONG iAddr ); 51 | 52 | BOOL CH34xReadSPI(); 53 | 54 | BOOL CH34xWriteSPI(); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![noswpatv3](http://zoobab.wdfiles.com/local--files/start/noupcv3.jpg)](https://ffii.org/donate-now-to-save-europe-from-software-patents-says-ffii/) 2 | [![noswpatv3](http://zoobab.wdfiles.com/local--files/start/noupcv3.jpg)](https://ffii.org/donate-now-to-save-europe-from-software-patents-says-ffii/) 3 | About 4 | ===== 5 | 6 | This is a copy of CH341PAR_LINUX.ZIP published by WCH: 7 | 8 | http://www.wch.cn/download/CH341PAR_LINUX_ZIP.html 9 | 10 | This is a parallel port driver (EPP, MEM) for ch341 chip. 11 | 12 | Screenshots 13 | =========== 14 | 15 | Everybody love screenshots. 16 | 17 | GPIO tab: 18 | 19 | ![CH341 GPIO tab](https://raw.githubusercontent.com/zoobab/ch341-parport/master/ch341-gpio.png) 20 | 21 | MEM tab: 22 | 23 | ![CH341 MEM tab](https://raw.githubusercontent.com/zoobab/ch341-parport/master/ch341-parport-mem.png) 24 | 25 | How to toggle the D5 GPIO 26 | ========================= 27 | 28 | First of all, you have to connect the 2 pins SDA+GND together, for me I did it with a jumper on my Electrodragon board (http://www.zoobab.com/ch341-usb-spi-i2c-uart-isp-dongle#toc5). You should see the board in EPP/I2C mode with the USB VID:PID 1a86:5512, with lsusb output: 29 | 30 | ``` 31 | root@zoobab-ThinkPad-X200:~/ch341-parport/CH341PAR_LINUX/demo# lsusb 32 | Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub 33 | Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub 34 | Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub 35 | Bus 006 Device 003: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse 36 | Bus 006 Device 023: ID 1a86:5512 QinHeng Electronics CH341 in EPP/MEM/I2C mode, EPP/I2C adapter 37 | ``` 38 | 39 | You should then load the kernel module: 40 | ``` 41 | root@zoobab-ThinkPad-X200:~/ch341-parport/CH341PAR_LINUX/driver# insmod ./ch34x_pis.ko 42 | root@zoobab-ThinkPad-X200:~/ch341-parport/CH341PAR_LINUX/driver# dmesg 43 | [...] 44 | [ 5711.969691] /home/zoobab/ch341-parport/CH341PAR_LINUX/driver/ch34x_pis.c 1119: CH34x_pis-0 now disconnected 45 | [ 5713.322777] /home/zoobab/ch341-parport/CH341PAR_LINUX/driver/ch34x_pis.c 1037: Found a bulk in endpoint 46 | [ 5713.322787] /home/zoobab/ch341-parport/CH341PAR_LINUX/driver/ch34x_pis.c 1046: Found a bulk out endpoint 47 | [ 5713.322791] /home/zoobab/ch341-parport/CH341PAR_LINUX/driver/ch34x_pis.c 1053: Found a interrupt in endpoint 48 | [ 5713.322963] /home/zoobab/ch341-parport/CH341PAR_LINUX/driver/ch34x_pis.c 1069: Ch34x_pis device now attached to ch34x_pis-0 49 | [ 5713.323049] usbcore: registered new interface driver ch34x_pis 50 | ``` 51 | 52 | You should see a new device in /dev called /dev/ch34x_pis0: 53 | ``` 54 | root@zoobab-ThinkPad-X200:~/ch341-parport/CH341PAR_LINUX/driver# ls -l /dev/ch34x_pis* 55 | lrwxrwxrwx 1 root root 10 apr 13 20:18 /dev/ch34x_pis -> ch34x_pis0 56 | crw------- 1 root root 180, 0 apr 13 21:47 /dev/ch34x_pis0 57 | ``` 58 | Note that I had to make a symlink from /dev/ch34x_pis to /dev/ch34x_pis0 to get the CLI demo app working. 59 | 60 | You can set the pin D5 HIGH with 0x60, and LOW with 0x50: 61 | ``` 62 | root@zoobab-ThinkPad-X200:~/ch341-parport/CH341PAR_LINUX/demo# ./DEMO 63 | Open sucessful 64 | drv_version : WCH CH34x Driver Version V0.1 65 | VendorId : 0x0030 66 | This is main menu listed 67 | -->1: EEPROM TEST 68 | -->2: EPP TEST 69 | -->3: MEM TEST 70 | -->4: SPI FLASH TEST( SST25VF512 ) 71 | -->5: SETOUTPUT TEST 72 | -->6: SET_D5_D0 TEST 73 | Please enter your selection: 74 | 6 75 | You choose 6 76 | input the direction data(Hex): 77 | 0x3F 78 | input the control data(Hex): 79 | 0x60 80 | ByteBuffer:ab a0 7f 20 Write.Lenth:4 81 | 82 | enter 'q' to exit or 'b' to come back 83 | b 84 | This is main menu listed 85 | -->1: EEPROM TEST 86 | -->2: EPP TEST 87 | -->3: MEM TEST 88 | -->4: SPI FLASH TEST( SST25VF512 ) 89 | -->5: SETOUTPUT TEST 90 | -->6: SET_D5_D0 TEST 91 | Please enter your selection: 92 | 6 93 | You choose 6 94 | input the direction data(Hex): 95 | 0x3F 96 | input the control data(Hex): 97 | 0x50 98 | ByteBuffer:ab 90 7f 20 Write.Lenth:4 99 | 100 | enter 'q' to exit or 'b' to come back 101 | ``` 102 | 103 | Now I have to find the other values for the other pins D0-D7. 104 | 105 | * D4: HIGH=0x10 LOW=0x20 106 | * D3: HIGH=0x LOW=0x 107 | * D2: HIGH=0x LOW=0x 108 | * D1: HIGH=0x LOW=0x 109 | * D0: HIGH=0x LOW=0x 110 | 111 | Todo 112 | ==== 113 | 114 | * compile it on different kernel versions 115 | ** works on Ubuntu 16.04 116 | * find how to toggle D0-D7 pins in GPIO mode 117 | * sniff USB packets and make a libusb tool 118 | -------------------------------------------------------------------------------- /CH341PAR_LINUX/demo/ch34x_lib.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | //**************************************** 4 | //** Copyright (C) W.ch 2013 ** 5 | //** Web: http://www.wch.cn ** 6 | //**************************************** 7 | //** LIB for USB interface chip CH341 ** 8 | //** C, LINUX ** 9 | //**************************************** 10 | // 11 | // 12 | #ifndef _CH34X_LIB_H 13 | #define _CH34X_LIB_H 14 | 15 | #ifndef UCHAR 16 | #define UCHAR unsigned char 17 | #endif 18 | 19 | #ifndef USHORT 20 | #define USHORT unsigned short 21 | #endif 22 | 23 | #ifndef ULONG 24 | #define ULONG unsigned long 25 | #endif 26 | 27 | #ifndef PUCHAR 28 | #define PUCHAR unsigned char * 29 | #endif 30 | 31 | #ifndef PCHAR 32 | #define PCHAR char * 33 | #endif 34 | 35 | #ifndef PUSHORT 36 | #define PUSHORT unsigned short * 37 | #endif 38 | 39 | #ifndef PULONG 40 | #define PULONG unsigned long * 41 | #endif 42 | 43 | #ifndef VOID 44 | #define VOID void 45 | #endif 46 | 47 | #ifndef PVOID 48 | #define PVOID void * 49 | #endif 50 | 51 | #define true 1 52 | #define false 0 53 | 54 | #ifndef min 55 | #define min( x, y ) (((x) < (y)) ? (x) : (y)) 56 | #endif 57 | 58 | #ifndef max 59 | #define max( x, y ) (((x) < (y)) ? (y) : (x)) 60 | #endif 61 | 62 | typedef enum 63 | { 64 | FALSE_H = 0, 65 | TRUE_H = !FALSE_H 66 | }BOOL; 67 | 68 | #define CH341_PACKET_LENGTH 32 69 | #define CH341_PKT_LEN_SHORT 8 70 | 71 | #define CH341_MAX_NUMBER 16 72 | #define MAX_BUFFER_LENGTH 0x1000 73 | #define DEFAULT_BUFFER_LEN 0x0400 74 | 75 | 76 | //CH341 endpointer addr 77 | #define CH341_ENDP_INTER_UP 0x81 // Interrupt up endpoint 78 | #define CH341_ENDP_INTER_DOWN 0x01 // Interrupt down endpoint 79 | #define CH341_ENDP_DATA_UP 0x82 // Data up endpoint 80 | #define CH341_ENDP_DATA_DOWN 0x02 // Data down endpoint 81 | 82 | 83 | 84 | #define PipeDeviceCtrl 0x00000004 85 | #define PipeInterUp 0x00000005 86 | #define PipeDataUp 0x00000006 87 | #define PipeDataDown 0x00000007 88 | 89 | #define CH341_VENDOR_READ 0xC0 //CH341 Read Command 90 | #define CH341_VENDOR_WRITE 0x40 //CH341 Write Command 91 | 92 | 93 | 94 | 95 | #define CH341_PARA_INIT 0xB1 // Init para 96 | #define CH341_I2C_STATUS 0x52 // Get I2C Interface State 97 | #define CH341_I2C_COMMAND 0x53 // Send I2C Command 98 | 99 | #define CH341_PARA_CMD_R0 0xAC // Read Data0 From Para 100 | #define CH341_PARA_CMD_R1 0xAD // Read Data1 From Para 101 | #define CH341_PARA_CMD_W0 0xA6 // Write Data0 From Para 102 | #define CH341_PARA_CMD_W1 0xA7 // Write Data1 From Para 103 | #define CH341_PARA_CMD_STS 0xA0 // Get Para State 104 | 105 | 106 | #define CH341A_CMD_SET_OUTPUT 0xA1 // Set Para Output 107 | #define CH341A_CMD_IO_ADDR 0xA2 //MEM Addr write/read 108 | #define CH341A_CMD_PRINT_OUT 0xA3 // Print output 109 | #define CH341A_CMD_PWM_OUT 0xA4 // PWM Out Command 110 | #define CH341A_CMD_SHORT_PKT 0xA5 //short package 111 | #define CH341A_CMD_SPI_STREAM 0xA8 //SPI Interface Command 112 | //#define mCH341A_CMD_SIO_STREAM 0xA9 113 | #define CH341A_CMD_I2C_STREAM 0xAA // I2C Interface Command 114 | #define CH341A_CMD_UIO_STREAM 0xAB // UIO Interface Command 115 | #define CH341A_CMD_PIO_STREAM 0xAE // PIO Interface Command 116 | 117 | 118 | #define CH341A_BUF_CLEAR 0xB2 // clear uncompleted data 119 | #define CH341A_I2C_CMD_X 0x54 // Send I2C Interface command 120 | #define CH341A_DELAY_MS 0x5E // Set Delay(ms) 121 | #define CH341A_GET_VER 0x5F // Get Chip Version 122 | 123 | // CH341 Write/Read Max Length Once in EPP/MEM Mode 124 | #define CH341_EPP_IO_MAX ( mCH341_PACKET_LENGTH - 1 ) 125 | #define CH341A_EPP_IO_MAX 0xFF // CH341A Write/Read Max Length Once in EPP/MEM Mode 126 | 127 | #define CH341A_CMD_IO_ADDR_W 0x00 //Mem Write 128 | #define CH341A_CMD_IO_ADDR_R 0x80 //MEM Read 129 | 130 | #define CH341A_CMD_I2C_STM_STA 0x74 //I2C Stream Start Command 131 | #define CH341A_CMD_I2C_STM_STO 0x75 //I2C Stream Stop byte Command 132 | #define CH341A_CMD_I2C_STM_OUT 0x80 //I2C Stream Out Command 133 | #define CH341A_CMD_I2C_STM_IN 0xC0 //I2C Stream In Command 134 | #define CH341A_CMD_I2C_STM_MAX ( min( 0x3F, mCH341_PACKET_LENGTH ) ) //I2C Stream Max Length 135 | #define CH341A_CMD_I2C_STM_SET 0x60 //I2C Stream Set Mode 136 | //-->bit2 spi io (0: one in one out ; 1: two in two out) 137 | //-->bit1~0 I2C SCL Rate 138 | #define CH341A_CMD_I2C_STM_US 0x40 //I2C Stream Delay(us) 139 | #define CH341A_CMD_I2C_STM_MS 0x50 //I2C Stream Delay(ms) 140 | #define CH341A_CMD_I2C_STM_DLY 0x0F //I2C Stream Set Max Delay 141 | #define CH341A_CMD_I2C_STM_END 0x00 //I2C Stream End Command 142 | 143 | #define CH341A_CMD_UIO_STM_IN 0x00 // UIO Interface In ( D0 ~ D7 ) 144 | #define CH341A_CMD_UIO_STM_DIR 0x40 // UIO interface Dir( set dir of D0~D5 ) 145 | #define CH341A_CMD_UIO_STM_OUT 0x80 // UIO Interface Output(D0~D5) 146 | #define CH341A_CMD_UIO_STM_US 0xC0 // UIO Interface Delay Command( us ) 147 | #define CH341A_CMD_UIO_STM_END 0x20 // UIO Interface End Command 148 | 149 | 150 | #define CH341_PARA_MODE_EPP 0x00 151 | #define CH341_PARA_MODE_EPP17 0x00 152 | #define CH341_PARA_MODE_EPP19 0x01 153 | #define CH341_PARA_MODE_MEM 0x02 154 | #define CH341_PARA_MODE_ECP 0x03 155 | 156 | #define StateBitERR 0x00000100 157 | #define StateBitPEMP 0x00000200 158 | #define StateBitINT 0x00000400 159 | #define StateBitSLCT 0x00000800 160 | #define StateBitWAIT 0x00002000 161 | #define StateBitDATAS 0x00004000 162 | #define StateBitADDRS 0x00008000 163 | #define StateBitRESET 0x00010000 164 | #define StateBitWRITE 0x00020000 165 | #define StateBitSCL 0x00400000 166 | #define StateBitSDA 0x00800000 167 | 168 | typedef enum _EEPROM_TYPE { 169 | ID_24C01, 170 | ID_24C02, 171 | ID_24C04, 172 | ID_24C08, 173 | ID_24C16, 174 | ID_24C32, 175 | ID_24C64, 176 | ID_24C128, 177 | ID_24C256, 178 | ID_24C512, 179 | ID_24C1024, 180 | ID_24C2048, 181 | ID_24C4096 182 | } EEPROM_TYPE; 183 | 184 | int CH34xOpenDevice(UCHAR index); 185 | 186 | void CH34xCloseDevice(); 187 | 188 | BOOL CH34x_GetDrvVer( char *drv_version ); 189 | 190 | BOOL CH34x_GetVendorId( PULONG VendorId ); 191 | 192 | BOOL CH34xSetParaMode( ULONG Mode ); 193 | 194 | BOOL CH34xInitParallel( ULONG Mode ); 195 | 196 | int CH34xEppRead( PUCHAR oBuffer, 197 | ULONG ioLength, 198 | ULONG PipeMode ); // PipiMode->0 : read data 199 | // PipeMode->1 : read Addr 200 | 201 | int CH34xEppWrite( PUCHAR iBuffer, 202 | ULONG ioLength, 203 | ULONG PipeMode ); // PipeMode->0 : write data 204 | // PipeMode->1 : write data 205 | 206 | int CH34xEppReadData( PUCHAR oBuffer, // input buffer 207 | ULONG ioLength ); //wanted length of read 208 | 209 | int CH34xEppWriteData( PUCHAR iBuffer, 210 | ULONG ioLength ); 211 | 212 | int CH34xEppWriteAddr( PUCHAR iBuffer, 213 | ULONG ioLength ); 214 | 215 | int CH34xEppReadAddr( PUCHAR oBuffer, 216 | ULONG ioLength ); 217 | 218 | int CH34xEppSetAddr( ULONG iAddr ); //EPP: WR#=0,DS#=1,AS#=0,D0~D7 output 219 | 220 | BOOL CH34xInitMEM(void); 221 | 222 | int CH34xMEMReadData( PUCHAR oBuffer, 223 | ULONG ioLength, 224 | ULONG PipeMode ); 225 | 226 | int CH34xMEMWriteData( PUCHAR iBuffer, 227 | ULONG ioLength, 228 | ULONG PipeMode ); 229 | 230 | BOOL CH34xSetStream( ULONG Mode ); 231 | 232 | BOOL CH34xSetDelaymS( ULONG iDelay ); 233 | 234 | BOOL CH34xReadData( PVOID oBuffer, 235 | PULONG ioLength ); 236 | 237 | BOOL CH34xWriteData( PVOID iBuffer, 238 | PULONG ioLength ); 239 | 240 | BOOL CH34xWriteRead( ULONG iWriteLength, 241 | PVOID iWriteBuffer, 242 | /* ULONG iReadStep, 243 | ULONG iReadTimes,*/ 244 | PULONG oReadLength, 245 | PVOID oReadBuffer ); 246 | 247 | BOOL CH34xSetOutput( ULONG iEnable, ULONG iSetDirOut, ULONG iSetDataOut ); 248 | 249 | BOOL CH34xSet_D5_D0( UCHAR iSetDirOut,UCHAR iSetDataOut); 250 | 251 | BOOL CH34xStreamI2C( ULONG iWriteLength, PVOID iWriteBuffer, 252 | ULONG iReadLength, PVOID oReadBuffer); 253 | 254 | BOOL CH34xReadEEPROM( EEPROM_TYPE iEepromID, 255 | ULONG iAddr, 256 | ULONG iLength, 257 | PUCHAR oBuffer ); 258 | 259 | BOOL CH34xWriteEEPROM( EEPROM_TYPE iEepromID, 260 | ULONG iAddr, 261 | ULONG iLength, 262 | PUCHAR iBuffer ); 263 | 264 | BOOL CH34xStreamSPIx( ULONG iChipSelect, 265 | ULONG iLength, 266 | PVOID ioBuffer, 267 | PVOID ioBuffer2 ); 268 | 269 | BOOL CH34xStreamSPI4( ULONG iChipSelect, 270 | ULONG iLength, 271 | PVOID ioBuffer ); 272 | 273 | 274 | 275 | #endif 276 | -------------------------------------------------------------------------------- /CH341PAR_LINUX/lib/ch34x_lib.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | //**************************************** 4 | //** Copyright (C) W.ch 2013 ** 5 | //** Web: http://www.wch.cn ** 6 | //**************************************** 7 | //** LIB for USB interface chip CH341 ** 8 | //** C, LINUX ** 9 | //**************************************** 10 | // 11 | // 12 | #ifndef _CH34X_LIB_H 13 | #define _CH34X_LIB_H 14 | 15 | #ifndef UCHAR 16 | #define UCHAR unsigned char 17 | #endif 18 | 19 | #ifndef USHORT 20 | #define USHORT unsigned short 21 | #endif 22 | 23 | #ifndef ULONG 24 | #define ULONG unsigned long 25 | #endif 26 | 27 | #ifndef PUCHAR 28 | #define PUCHAR unsigned char * 29 | #endif 30 | 31 | #ifndef PCHAR 32 | #define PCHAR char * 33 | #endif 34 | 35 | #ifndef PUSHORT 36 | #define PUSHORT unsigned short * 37 | #endif 38 | 39 | #ifndef PULONG 40 | #define PULONG unsigned long * 41 | #endif 42 | 43 | #ifndef VOID 44 | #define VOID void 45 | #endif 46 | 47 | #ifndef PVOID 48 | #define PVOID void * 49 | #endif 50 | 51 | #define true 1 52 | #define false 0 53 | 54 | #ifndef min 55 | #define min( x, y ) (((x) < (y)) ? (x) : (y)) 56 | #endif 57 | 58 | #ifndef max 59 | #define max( x, y ) (((x) < (y)) ? (y) : (x)) 60 | #endif 61 | 62 | typedef enum 63 | { 64 | FALSE_H = 0, 65 | TRUE_H = !FALSE_H 66 | }BOOL; 67 | 68 | #define CH341_PACKET_LENGTH 32 69 | #define CH341_PKT_LEN_SHORT 8 70 | 71 | #define CH341_MAX_NUMBER 16 72 | #define MAX_BUFFER_LENGTH 0x1000 73 | #define DEFAULT_BUFFER_LEN 0x0400 74 | 75 | 76 | //CH341 endpointer addr 77 | #define CH341_ENDP_INTER_UP 0x81 // Interrupt up endpoint 78 | #define CH341_ENDP_INTER_DOWN 0x01 // Interrupt down endpoint 79 | #define CH341_ENDP_DATA_UP 0x82 // Data up endpoint 80 | #define CH341_ENDP_DATA_DOWN 0x02 // Data down endpoint 81 | 82 | 83 | 84 | #define PipeDeviceCtrl 0x00000004 85 | #define PipeInterUp 0x00000005 86 | #define PipeDataUp 0x00000006 87 | #define PipeDataDown 0x00000007 88 | 89 | #define CH341_VENDOR_READ 0xC0 //CH341 Read Command 90 | #define CH341_VENDOR_WRITE 0x40 //CH341 Write Command 91 | 92 | 93 | 94 | 95 | #define CH341_PARA_INIT 0xB1 // Init para 96 | #define CH341_I2C_STATUS 0x52 // Get I2C Interface State 97 | #define CH341_I2C_COMMAND 0x53 // Send I2C Command 98 | 99 | #define CH341_PARA_CMD_R0 0xAC // Read Data0 From Para 100 | #define CH341_PARA_CMD_R1 0xAD // Read Data1 From Para 101 | #define CH341_PARA_CMD_W0 0xA6 // Write Data0 From Para 102 | #define CH341_PARA_CMD_W1 0xA7 // Write Data1 From Para 103 | #define CH341_PARA_CMD_STS 0xA0 // Get Para State 104 | 105 | 106 | #define CH341A_CMD_SET_OUTPUT 0xA1 // Set Para Output 107 | #define CH341A_CMD_IO_ADDR 0xA2 //MEM Addr write/read 108 | #define CH341A_CMD_PRINT_OUT 0xA3 // Print output 109 | #define CH341A_CMD_PWM_OUT 0xA4 // PWM Out Command 110 | #define CH341A_CMD_SHORT_PKT 0xA5 //short package 111 | #define CH341A_CMD_SPI_STREAM 0xA8 //SPI Interface Command 112 | //#define mCH341A_CMD_SIO_STREAM 0xA9 113 | #define CH341A_CMD_I2C_STREAM 0xAA // I2C Interface Command 114 | #define CH341A_CMD_UIO_STREAM 0xAB // UIO Interface Command 115 | #define CH341A_CMD_PIO_STREAM 0xAE // PIO Interface Command 116 | 117 | 118 | #define CH341A_BUF_CLEAR 0xB2 // clear uncompleted data 119 | #define CH341A_I2C_CMD_X 0x54 // Send I2C Interface command 120 | #define CH341A_DELAY_MS 0x5E // Set Delay(ms) 121 | #define CH341A_GET_VER 0x5F // Get Chip Version 122 | 123 | // CH341 Write/Read Max Length Once in EPP/MEM Mode 124 | #define CH341_EPP_IO_MAX ( mCH341_PACKET_LENGTH - 1 ) 125 | #define CH341A_EPP_IO_MAX 0xFF // CH341A Write/Read Max Length Once in EPP/MEM Mode 126 | 127 | #define CH341A_CMD_IO_ADDR_W 0x00 //Mem Write 128 | #define CH341A_CMD_IO_ADDR_R 0x80 //MEM Read 129 | 130 | #define CH341A_CMD_I2C_STM_STA 0x74 //I2C Stream Start Command 131 | #define CH341A_CMD_I2C_STM_STO 0x75 //I2C Stream Stop byte Command 132 | #define CH341A_CMD_I2C_STM_OUT 0x80 //I2C Stream Out Command 133 | #define CH341A_CMD_I2C_STM_IN 0xC0 //I2C Stream In Command 134 | #define CH341A_CMD_I2C_STM_MAX ( min( 0x3F, mCH341_PACKET_LENGTH ) ) //I2C Stream Max Length 135 | #define CH341A_CMD_I2C_STM_SET 0x60 //I2C Stream Set Mode 136 | //-->bit2 spi io (0: one in one out ; 1: two in two out) 137 | //-->bit1~0 I2C SCL Rate 138 | #define CH341A_CMD_I2C_STM_US 0x40 //I2C Stream Delay(us) 139 | #define CH341A_CMD_I2C_STM_MS 0x50 //I2C Stream Delay(ms) 140 | #define CH341A_CMD_I2C_STM_DLY 0x0F //I2C Stream Set Max Delay 141 | #define CH341A_CMD_I2C_STM_END 0x00 //I2C Stream End Command 142 | 143 | #define CH341A_CMD_UIO_STM_IN 0x00 // UIO Interface In ( D0 ~ D7 ) 144 | #define CH341A_CMD_UIO_STM_DIR 0x40 // UIO interface Dir( set dir of D0~D5 ) 145 | #define CH341A_CMD_UIO_STM_OUT 0x80 // UIO Interface Output(D0~D5) 146 | #define CH341A_CMD_UIO_STM_US 0xC0 // UIO Interface Delay Command( us ) 147 | #define CH341A_CMD_UIO_STM_END 0x20 // UIO Interface End Command 148 | 149 | 150 | #define CH341_PARA_MODE_EPP 0x00 151 | #define CH341_PARA_MODE_EPP17 0x00 152 | #define CH341_PARA_MODE_EPP19 0x01 153 | #define CH341_PARA_MODE_MEM 0x02 154 | #define CH341_PARA_MODE_ECP 0x03 155 | 156 | #define StateBitERR 0x00000100 157 | #define StateBitPEMP 0x00000200 158 | #define StateBitINT 0x00000400 159 | #define StateBitSLCT 0x00000800 160 | #define StateBitWAIT 0x00002000 161 | #define StateBitDATAS 0x00004000 162 | #define StateBitADDRS 0x00008000 163 | #define StateBitRESET 0x00010000 164 | #define StateBitWRITE 0x00020000 165 | #define StateBitSCL 0x00400000 166 | #define StateBitSDA 0x00800000 167 | 168 | typedef enum _EEPROM_TYPE { 169 | ID_24C01, 170 | ID_24C02, 171 | ID_24C04, 172 | ID_24C08, 173 | ID_24C16, 174 | ID_24C32, 175 | ID_24C64, 176 | ID_24C128, 177 | ID_24C256, 178 | ID_24C512, 179 | ID_24C1024, 180 | ID_24C2048, 181 | ID_24C4096 182 | } EEPROM_TYPE; 183 | 184 | int CH34xOpenDevice(UCHAR index); 185 | 186 | void CH34xCloseDevice(); 187 | 188 | BOOL CH34x_GetDrvVer( char *drv_version ); 189 | 190 | BOOL CH34x_GetVendorId( PULONG VendorId ); 191 | 192 | BOOL CH34xSetParaMode( ULONG Mode ); 193 | 194 | BOOL CH34xInitParallel( ULONG Mode ); 195 | 196 | int CH34xEppRead( PUCHAR oBuffer, 197 | ULONG ioLength, 198 | ULONG PipeMode ); // PipiMode->0 : read data 199 | // PipeMode->1 : read Addr 200 | 201 | int CH34xEppWrite( PUCHAR iBuffer, 202 | ULONG ioLength, 203 | ULONG PipeMode ); // PipeMode->0 : write data 204 | // PipeMode->1 : write data 205 | 206 | int CH34xEppReadData( PUCHAR oBuffer, // input buffer 207 | ULONG ioLength ); //wanted length of read 208 | 209 | int CH34xEppWriteData( PUCHAR iBuffer, 210 | ULONG ioLength ); 211 | 212 | int CH34xEppWriteAddr( PUCHAR iBuffer, 213 | ULONG ioLength ); 214 | 215 | int CH34xEppReadAddr( PUCHAR oBuffer, 216 | ULONG ioLength ); 217 | 218 | int CH34xEppSetAddr( ULONG iAddr ); //EPP: WR#=0,DS#=1,AS#=0,D0~D7 output 219 | 220 | BOOL CH34xInitMEM(void); 221 | 222 | int CH34xMEMReadData( PUCHAR oBuffer, 223 | ULONG ioLength, 224 | ULONG PipeMode ); 225 | 226 | int CH34xMEMWriteData( PUCHAR iBuffer, 227 | ULONG ioLength, 228 | ULONG PipeMode ); 229 | 230 | BOOL CH34xSetStream( ULONG Mode ); 231 | 232 | BOOL CH34xSetDelaymS( ULONG iDelay ); 233 | 234 | BOOL CH34xReadData( PVOID oBuffer, 235 | PULONG ioLength ); 236 | 237 | BOOL CH34xWriteData( PVOID iBuffer, 238 | PULONG ioLength ); 239 | 240 | BOOL CH34xWriteRead( ULONG iWriteLength, 241 | PVOID iWriteBuffer, 242 | /* ULONG iReadStep, 243 | ULONG iReadTimes,*/ 244 | PULONG oReadLength, 245 | PVOID oReadBuffer ); 246 | 247 | BOOL CH34xSetOutput( ULONG iEnable, ULONG iSetDirOut, ULONG iSetDataOut ); 248 | 249 | BOOL CH34xSet_D5_D0( UCHAR iSetDirOut,UCHAR iSetDataOut); 250 | 251 | BOOL CH34xStreamI2C( ULONG iWriteLength, PVOID iWriteBuffer, 252 | ULONG iReadLength, PVOID oReadBuffer); 253 | 254 | BOOL CH34xReadEEPROM( EEPROM_TYPE iEepromID, 255 | ULONG iAddr, 256 | ULONG iLength, 257 | PUCHAR oBuffer ); 258 | 259 | BOOL CH34xWriteEEPROM( EEPROM_TYPE iEepromID, 260 | ULONG iAddr, 261 | ULONG iLength, 262 | PUCHAR iBuffer ); 263 | 264 | BOOL CH34xStreamSPIx( ULONG iChipSelect, 265 | ULONG iLength, 266 | PVOID ioBuffer, 267 | PVOID ioBuffer2 ); 268 | 269 | BOOL CH34xStreamSPI4( ULONG iChipSelect, 270 | ULONG iLength, 271 | PVOID ioBuffer ); 272 | 273 | 274 | 275 | #endif 276 | -------------------------------------------------------------------------------- /CH341PAR_LINUX/demo/ch34x_demo.c: -------------------------------------------------------------------------------- 1 | /* 2 | *ch36x_demo.c for ch365/ch367/ch368 pci card of WCH 3 | * 4 | ********************************************************************** 5 | *********** Copyright (C) WCH 2013.10.28 *************** 6 | *********** web: www.wch.cn *************** 7 | *********** AUTHOR: TECH33 (tech@wch.cn) *************** 8 | *********** Used for PCI/PCIe Chip (CH365/7/8) *************** 9 | *********** Nanjing QinHeng Electronics Co.,Ltd *************** 10 | ********************************************************************** 11 | * 12 | * Running Environment: Linux 13 | * This file is used for testing I/O\MEM\Configuration\ (Read and Write) 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "ch34x_lib.h" 24 | #include "flash_sst.h" 25 | 26 | #ifndef CH34x_DEBUG 27 | #define CH34x_DEBUG 28 | #endif 29 | 30 | #ifdef CH34x_DEBUG 31 | #define dbg( format, arg...) printf( format "\n", ##arg ); 32 | #endif 33 | #define err( format, arg... ) \ 34 | printf( "error %d: " format "\n", __LINE__, ##arg ) 35 | 36 | extern int dev_fd; 37 | struct{ 38 | void *DeviceId; 39 | void *Addr; 40 | unsigned char *Byte; 41 | }i2c_device; 42 | 43 | 44 | ULONG enable_data; 45 | ULONG dir_data; 46 | ULONG con_data; 47 | 48 | /* 49 | * ******************************************************************** 50 | * InitPara() 51 | * Function : Init Parallel 52 | * ******************************************************************** 53 | */ 54 | int InitPara() 55 | { 56 | int retval; 57 | unsigned long iMode; 58 | iMode = 0x00; 59 | retval = CH34xSetParaMode( iMode ); 60 | if( retval == false ) 61 | { 62 | err("------>SetPara Error"); 63 | return false; 64 | } 65 | retval = CH34xInitParallel( iMode ); 66 | if( retval == false ) 67 | { 68 | err("------->Init Parallel Error\n"); 69 | return false; 70 | } 71 | return true; 72 | } 73 | 74 | /* 75 | * ******************************************************************** 76 | * CH34x_EppWrite() 77 | * Function : EPP Write,Write 256 bytes into EPP 78 | * ******************************************************************** 79 | */ 80 | int CH34x_EppWrite() 81 | { 82 | int retval, i; 83 | unsigned long iLength; 84 | // unsigned char iBuffer[64] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42}; 85 | unsigned char iBuffer[255]; 86 | for( i = 0; i <= 255; i++ ) 87 | iBuffer[i] = i; 88 | iLength = 256; 89 | retval = CH34xEppWriteData( iBuffer, iLength ); 90 | if( retval == false ) 91 | { 92 | err("----------------->Write Error"); 93 | return false; 94 | } 95 | return true; 96 | } 97 | 98 | /* 99 | * ******************************************************************** 100 | * CH34x_EppRead() 101 | * Function : EPP Read,Read 255 bytes from EPP 102 | * ******************************************************************** 103 | */ 104 | int CH34x_EppRead() 105 | { 106 | int retval,i; 107 | unsigned long ioLength; 108 | unsigned char ioBuffer[MAX_BUFFER_LENGTH]; 109 | ioLength = 256; 110 | retval = CH34xEppReadData( ioBuffer, ioLength ); 111 | if( retval != ioLength ) 112 | { 113 | err("------------->Read Error\n"); 114 | return false; 115 | } 116 | for( i = 0; i < ioLength; i++ ) 117 | { 118 | printf(" %d", ioBuffer[i] ); 119 | } 120 | printf("\n"); 121 | return true; 122 | } 123 | 124 | /* 125 | * ******************************************************************** 126 | * InitMEM() 127 | * Function : Init Memory 128 | * ******************************************************************** 129 | */ 130 | int InitMEM() 131 | { 132 | int retval; 133 | retval = CH34xInitMEM(); 134 | if( retval == false ) 135 | { 136 | err("------->Init Parallel Error\n"); 137 | return false; 138 | } 139 | return true; 140 | } 141 | 142 | /* 143 | * ******************************************************************** 144 | * CH34x_MEMWrite() 145 | * Function : MEM Write,Write 255 bytes into MEM 146 | * ******************************************************************** 147 | */ 148 | int CH34x_MEMWrite() 149 | { 150 | int retval,i; 151 | unsigned long iLength; 152 | // unsigned char iBuffer[64] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42}; 153 | unsigned char iBuffer[256]; 154 | for(i = 0; i < 256; i++) 155 | iBuffer[i] = i; 156 | iLength = 256; 157 | retval = CH34xMEMWriteData( iBuffer, iLength, 1 ); 158 | if( retval == false ) 159 | { 160 | err("----------------->Write Error"); 161 | return false; 162 | } 163 | return true; 164 | } 165 | 166 | /* 167 | * ******************************************************************** 168 | * CH34x_MEMRead() 169 | * Function : MEM Read,Read 259 bytes from MEM 170 | * ******************************************************************** 171 | */ 172 | int CH34x_MEMRead() 173 | { 174 | int retval,i; 175 | unsigned long ioLength; 176 | unsigned char ioBuffer[MAX_BUFFER_LENGTH]; 177 | ioLength = 258; 178 | retval = CH34xMEMReadData( ioBuffer, ioLength, 0 ); 179 | printf("ioLength is %d in MEM Read\n",retval); 180 | if( retval != ioLength ) 181 | { 182 | err("------------->Read Error\n"); 183 | return false; 184 | } 185 | for( i = 0; i <= ioLength; i++ ) 186 | { 187 | printf(" %d", ioBuffer[i] ); 188 | } 189 | printf("\n"); 190 | return true; 191 | } 192 | 193 | /* 194 | * ******************************************************************** 195 | * init_device( void ) 196 | * 197 | * Function : open device, Get Driver Version, Get Chip ID 198 | * ******************************************************************** 199 | */ 200 | int init_device( void ) 201 | { 202 | int retval = 0; 203 | 204 | system("clear"); 205 | dev_fd = CH34xOpenDevice( 0 ); 206 | if( dev_fd <= 0 ) 207 | { 208 | err("CH34xOpenDevice Open Error"); 209 | return -1; 210 | } 211 | dbg( "Open sucessful" ); 212 | //Get Driver Version 213 | char *drv_version = (char *)malloc( sizeof( char ) * 30 ); 214 | 215 | retval = CH34x_GetDrvVer( drv_version ); 216 | if( retval == false ) 217 | { 218 | err( "CH34x_GetDrvVer Error" ); 219 | return -1; 220 | } 221 | 222 | printf( "drv_version : %s\n", drv_version ); 223 | free( drv_version ); 224 | //Get Chip Version 225 | PULONG VendorId = (char *)malloc( sizeof(unsigned long)); 226 | retval = CH34x_GetVendorId( VendorId ); 227 | if( retval == false ) 228 | { 229 | err( "CH34x_GetVendorId Error" ); 230 | return -1; 231 | } 232 | printf( "VendorId : 0x%04x\n", *VendorId ); 233 | free( VendorId ); 234 | return true; 235 | 236 | } 237 | 238 | /* 239 | * ******************************************************************** 240 | * EEPROM_TEST( void ) 241 | * 242 | * Function : EEPROM Write/Read 243 | * ******************************************************************** 244 | */ 245 | void EEPROM_TEST( void ) 246 | { 247 | //Write EEPROM 248 | int retval = 0; 249 | UCHAR iBuf; 250 | printf("Please input a byte into EEPROM:\n"); 251 | scanf( "%x", &iBuf ); 252 | printf("You input 0x%x\n", iBuf); 253 | retval = CH34xWriteEEPROM( ID_24C08, 0x0000, 1, &iBuf ); 254 | if( retval == false ) 255 | { 256 | err("I2C Write Error"); 257 | return -1; 258 | } 259 | 260 | sleep(1); 261 | //Read EEPROM 262 | PUCHAR oBuffer ; 263 | oBuffer = (PUCHAR)malloc( sizeof(unsigned char) * 30 ); 264 | retval = CH34xReadEEPROM( ID_24C08, 0x0000, 20, oBuffer ); 265 | if( retval == false ) 266 | { 267 | err("I2C Read Error"); 268 | return -1; 269 | } 270 | printf("Output is 0x%x\n", oBuffer[0]); 271 | free( oBuffer ); 272 | } 273 | 274 | /* 275 | * ******************************************************************** 276 | * EPP_TEST() 277 | * 278 | * Function : EPP Write/Read 279 | * ******************************************************************** 280 | */ 281 | void EPP_TEST() 282 | { 283 | //EPP Write/Read 284 | int retval = 0; 285 | if((retval = InitPara()) == false) 286 | { 287 | err("Init Para Error\n"); 288 | } 289 | if((retval = CH34x_EppWrite()) == false ) 290 | { 291 | err("Epp Write Error\n"); 292 | } 293 | if((retval = CH34x_EppRead()) == false ) 294 | { 295 | err("Read Error"); 296 | } 297 | } 298 | 299 | /* 300 | * ******************************************************************** 301 | * MEM_TEST() 302 | * 303 | * Function : MEM Write/Read 304 | * ******************************************************************** 305 | */ 306 | void MEM_TEST() 307 | { 308 | //MEM Write/Read 309 | int retval = 0; 310 | if((retval = InitMEM()) == false) 311 | { 312 | err("Init MEM Error\n"); 313 | } 314 | if((retval = CH34x_MEMWrite()) == false ) 315 | { 316 | err("MEM Write Error\n"); 317 | } 318 | if((retval = CH34x_MEMRead()) == false ) 319 | { 320 | err("MEM Read Error"); 321 | } 322 | } 323 | 324 | /* 325 | * ******************************************************************** 326 | * SPI_FLASH_TEST() 327 | * 328 | * Function : FLASH Write/Read 329 | * Note: this function does not include save unused data 330 | * ******************************************************************** 331 | */ 332 | int SPI_FLASH_TEST() 333 | { 334 | //Read Block SPI ( MAX 1024 Every one ) 335 | /* UCHAR oBuffer[MAX_BUFFER_LENGTH]; 336 | if( CH34x_Flash_ReadBlock(NULL,0x00) == false ) 337 | { 338 | printf("Read block Error\n"); 339 | } 340 | */ 341 | 342 | if( CH34xWriteSPI() == false ) 343 | { 344 | printf("Write SPI Error\n"); 345 | return false; 346 | } 347 | if( CH34xReadSPI() == false ) 348 | { 349 | printf("Read SPI Error\n"); 350 | return false; 351 | } 352 | 353 | } 354 | 355 | 356 | /* 357 | * ******************************************************************** 358 | * SETOUTPUT_TEST() 359 | * 360 | * Function : Set direction and output data of CH341 361 | * Note: refer to fuction of CH34xSetOutput() in lib 362 | * ******************************************************************** 363 | */ 364 | int SETOUTPUT_TEST(void) 365 | { 366 | printf("input the enable data(Hex):\n"); 367 | scanf("%x",&enable_data); 368 | printf("input the direction data(Hex):\n"); 369 | scanf("%x",&dir_data); 370 | printf("input the control data(Hex):\n"); 371 | scanf("%x",&con_data); 372 | if( CH34xSetOutput(enable_data, dir_data, con_data) == false) 373 | { 374 | printf("Set Output Error!\n"); 375 | return false; 376 | } 377 | return true; 378 | } 379 | 380 | /* 381 | * ******************************************************************** 382 | * SETOUTPUT_TEST() 383 | * 384 | * Function : Set direction and output data of D5-D0 on CH341 385 | * Note: refer to fuction of CH34xSet_D5_D0() in lib 386 | * ******************************************************************** 387 | */ 388 | 389 | int SET_D5_D0_TEST(void) 390 | { 391 | printf("input the direction data(Hex):\n"); 392 | scanf("%x",&dir_data); 393 | printf("input the control data(Hex):\n"); 394 | scanf("%x",&con_data); 395 | if(CH34xSet_D5_D0((UCHAR)dir_data, (UCHAR)con_data) == false) 396 | { 397 | printf("Set D5_D0 Error!\n"); 398 | return false; 399 | } 400 | return true; 401 | } 402 | 403 | 404 | 405 | void ShowMainMenu( void ) 406 | { 407 | printf("This is main menu listed\n"); 408 | printf("-->1: EEPROM TEST\n"); 409 | printf("-->2: EPP TEST\n"); 410 | printf("-->3: MEM TEST\n"); 411 | printf("-->4: SPI FLASH TEST( SST25VF512 )\n"); 412 | printf("-->5: SETOUTPUT TEST\n"); 413 | printf("-->6: SET_D5_D0 TEST\n"); 414 | printf("Please enter your selection:\n"); 415 | 416 | } 417 | 418 | int main( int argc, char **argv ) 419 | { 420 | int ch; 421 | char button = '\0'; 422 | int retval = 0; 423 | retval = init_device(); 424 | if( retval == -1 ) 425 | { 426 | printf("Init device error\n"); 427 | return false; 428 | } 429 | while(1) 430 | { 431 | ShowMainMenu(); 432 | scanf("%d",&ch); 433 | printf("You choose %d \n",ch); 434 | switch(ch) 435 | { 436 | case 1: 437 | EEPROM_TEST(); 438 | break; 439 | case 2: 440 | EPP_TEST(); 441 | break; 442 | case 3: 443 | MEM_TEST(); 444 | break; 445 | case 4: 446 | SPI_FLASH_TEST(); 447 | break; 448 | case 5: 449 | SETOUTPUT_TEST(); 450 | break; 451 | case 6: 452 | SET_D5_D0_TEST(); 453 | break; 454 | default: 455 | break; 456 | } 457 | do 458 | { 459 | printf("\nenter 'q' to exit or 'b' to come back\n"); 460 | scanf(" %c", &button); 461 | }while( button != 'q' && button != 'b' ); 462 | if( button == 'q' ) 463 | break; 464 | } 465 | 466 | CH34xCloseDevice(); 467 | return 0; 468 | } 469 | 470 | int ReadFlashId() 471 | { 472 | ULONG mLen, iChipselect; 473 | UCHAR mWrBuf[6]; 474 | mWrBuf[0] = ReadID; 475 | mWrBuf[1] = 0x00; 476 | mWrBuf[2] = 0x00; 477 | mWrBuf[3] = 0x00; 478 | iChipselect = 0x80; 479 | mLen = 6; 480 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 481 | return false; 482 | else 483 | return mWrBuf[5]; 484 | } 485 | 486 | BOOL CH34xWriteEnable() 487 | { 488 | ULONG mLen, iChipselect; 489 | UCHAR mWrBuf[2]; 490 | mWrBuf[0] = WREN; 491 | mLen = 2; 492 | iChipselect = 0x80; 493 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 494 | return false; 495 | else 496 | return true; 497 | } 498 | 499 | BOOL CH34xSectorErase( ULONG StartAddr ) 500 | { 501 | ULONG mLen, iChipselect; 502 | UCHAR mWrBuf[4]; 503 | if( CH34xWriteEnable() == false ) 504 | return false; 505 | mWrBuf[0] = Sector_Erase; 506 | mWrBuf[1] = (UCHAR)( StartAddr >> 16 & 0xff ); 507 | mWrBuf[2] = (UCHAR)( StartAddr >> 8 & 0xf0 ); 508 | mWrBuf[3] = 0x00; 509 | mLen = 4; 510 | iChipselect = 0x80; 511 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 512 | return false; 513 | 514 | if( CH34xFlash_Wait() == false ) 515 | return false; 516 | return true; 517 | } 518 | 519 | int CH34x_Flash_ReadByte( PVOID oBuffer, ULONG iAddr ) 520 | { 521 | ULONG mLen, iChipselect; 522 | UCHAR mWrBuf[16]; 523 | mLen = 16; 524 | iChipselect = 0x80; 525 | mWrBuf[0] = ReadByte; 526 | mWrBuf[1] = (UCHAR)( iAddr >> 16 & 0xff ); 527 | mWrBuf[2] = (UCHAR)( iAddr >> 8 & 0xff ); 528 | mWrBuf[3] = (UCHAR)( iAddr & 0xff ); 529 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 530 | return false; 531 | printf("Read SPI Data,First is %x,Second is %x\n",mWrBuf[4],mWrBuf[5]); 532 | } 533 | 534 | int CH34x_Flash_ReadBlock( PVOID oBuffer, ULONG iAddr) 535 | { 536 | ULONG mLen, iChipselect; 537 | UCHAR mWrBuf[MAX_BUFFER_LENGTH]; 538 | ULONG i; 539 | mLen = 33; 540 | iChipselect = 0x80; 541 | // iAddr = iAddr - iAddr % 0x1000; 542 | mWrBuf[0] = ReadByte; 543 | mWrBuf[1] = (UCHAR)( iAddr >> 16 & 0xff ); 544 | mWrBuf[2] = (UCHAR)( iAddr >> 8 & 0xff ); 545 | mWrBuf[3] = (UCHAR)( iAddr & 0xff ); 546 | if( CH34xStreamSPI4( iChipselect, mLen+4, mWrBuf ) == false ) 547 | return false; 548 | 549 | for( i = 0; i < mLen; i++ ) 550 | printf("index is %d, Value is %x\n",i,mWrBuf[i + 4]); 551 | return true; 552 | } 553 | 554 | BOOL CH34xFlash_Wait() 555 | { 556 | ULONG mLen, iChipselect; 557 | ULONG i = 0; 558 | UCHAR mWrBuf[3]; 559 | UCHAR status; 560 | mLen = 3; 561 | iChipselect = 0x80; 562 | mWrBuf[0] = RDSR; 563 | do{ 564 | mWrBuf[0] = RDSR; 565 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 566 | return false; 567 | status = mWrBuf[1]; 568 | }while( status & 1 ); 569 | return true; 570 | } 571 | 572 | BOOL CH34xFlashReadStatus() 573 | { 574 | ULONG mLen, iChipselect; 575 | UCHAR status; 576 | UCHAR mWrBuf[3]; 577 | iChipselect = 0x80; 578 | mLen = 3; 579 | mWrBuf[0] = RDSR; 580 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 581 | return false; 582 | status = mWrBuf[1]; 583 | if( status & 0x0c ) 584 | { 585 | mWrBuf[0] = EWSR; 586 | mLen = 1; 587 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 588 | return false; 589 | mLen = 2; 590 | memset( mWrBuf, 0, sizeof( UCHAR ) * mLen ); 591 | mWrBuf[0] = WRSR; 592 | mWrBuf[1] = status & (~0x0c); 593 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 594 | return false; 595 | } 596 | mWrBuf[0] = RDSR; 597 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 598 | return false; 599 | status = mWrBuf[1]; 600 | 601 | return true; 602 | } 603 | 604 | BOOL CH34x_Flash_Write( PVOID iBuffer, ULONG iAddr ) 605 | { 606 | ULONG i; 607 | ULONG iChipselect = 0x80; 608 | UCHAR mWrBuf[5]; 609 | ULONG mLen = 5; 610 | for( i = 0; i < 2; i++ ) 611 | { 612 | if( !CH34xWriteEnable() ) 613 | return false; 614 | mWrBuf[0] = Byte_Program; 615 | mWrBuf[1] = (UCHAR)(iAddr >> 16 & 0xff); 616 | mWrBuf[2] = (UCHAR)(iAddr >> 8 & 0xff); 617 | mWrBuf[3] = (UCHAR)(iAddr & 0xff); 618 | iAddr++; 619 | mWrBuf[4] = *((PUCHAR)iBuffer + i); 620 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 621 | return false; 622 | memset( mWrBuf, 0, sizeof( UCHAR ) * mLen ); 623 | if( !CH34xFlash_Wait() ) 624 | return false; 625 | } 626 | return true; 627 | } 628 | 629 | BOOL CH34xReadSPI() 630 | { 631 | ULONG mLen; 632 | CH34x_Flash_ReadByte( NULL, 0x0000 ); 633 | return true; 634 | } 635 | 636 | BOOL CH34xWriteSPI() 637 | { 638 | int retval; 639 | int i; 640 | PUCHAR BufData; 641 | BufData = malloc( sizeof( UCHAR ) * 4096 ); 642 | if( BufData == NULL ) 643 | { 644 | printf("malloc error\n"); 645 | } 646 | retval = CH34xFlashReadStatus(); 647 | if( retval == false ) 648 | { 649 | printf("error in flash status\n"); 650 | return false; 651 | } 652 | /* retval = CH34x_Flash_ReadByte( BufData, 0x0000 ); 653 | if( retval == false ) 654 | { 655 | printf("error in flash ReadByte\n"); 656 | return false; 657 | } 658 | */ 659 | retval = CH34xSectorErase( 0x0000 ); 660 | if( retval == false ) 661 | { 662 | printf("error in flash Sector Erase\n"); 663 | return false; 664 | } 665 | 666 | // BufData[0] = 0xaa; 667 | // BufData[1] = 0x55; 668 | printf("Please input 2 number:\n"); 669 | for( i = 0; i < 2; i++ ) 670 | scanf("%x", &BufData[i]); 671 | retval = CH34x_Flash_Write( BufData, 0x0000 ); 672 | if( retval == false ) 673 | { 674 | printf("error in flash Write\n"); 675 | return false; 676 | } 677 | free( BufData ); 678 | return true; 679 | 680 | } 681 | -------------------------------------------------------------------------------- /CH341PAR_LINUX/driver/ch34x_pis.c: -------------------------------------------------------------------------------- 1 | // Created on: Nov 28, 2013 2 | /* 3 | * File : ch34x_pis.c 4 | * 5 | ********************************************************************** 6 | *********** Copyright (C) WCH 2013.11.28 *************** 7 | *********** web: www.wch.cn *************** 8 | *********** AUTHOR: TECH33 (tech@wch.cn) *************** 9 | *********** Used for USB Interface Chip (CH341) *************** 10 | *********** Nanjing QinHeng Electronics Co.,Ltd *************** 11 | ********************************************************************** 12 | * 13 | * Running Environment: Linux 14 | * This file is used for CH34x in Epp/MEM/I2C/SPI 15 | * 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include 31 | #ifndef KERNEL_VERSION 32 | #define KERNEL_VERSION(ver, rel, seq) ((ver << 16) | (rel <<8) | (seq)) 33 | #endif 34 | 35 | #define DEBUG 36 | //#undef DEBUG 37 | 38 | #ifdef DEBUG 39 | #define dbg( format, arg... ) \ 40 | printk( KERN_DEBUG "%s %d: " format "\n", __FILE__, __LINE__, ##arg ) 41 | #else 42 | #define dbg( format, arg... ) do{} while(0) 43 | #endif 44 | 45 | #define err( format, arg... ) \ 46 | printk( KERN_ERR KBUILD_MODNAME ":" format "\n", __FILE__, __LINE__, ##arg) 47 | 48 | 49 | #define CH34x_VENDOR_ID 0x1A86 //Vendor Id 50 | #define CH34x_PRODUCT_ID 0x5512 //Product Id 51 | #define DRV_NAME "ch34x_pis" 52 | #define DRV_VERSION "WCH CH34x Driver Version V0.1" 53 | 54 | 55 | #define CH34x_MINOR_BASE 200 // 56 | #define WRITES_IN_FLIGHT 8 57 | #define CH34x_READ_SHORT 8 58 | #define CH34x_PACKET_LENGTH 32 59 | #define MAX_BUFFER_LENGTH 0x1000 60 | 61 | 62 | //Vendor define 63 | #define VENDOR_WRITE_TYPE 0x40 //vendor write command 64 | #define VENDOR_READ_TYPE 0XC0 //vendor read command 65 | 66 | // 67 | #define CH34x_PARA_INIT 0xB1 // Init Parallel 68 | #define CH34x_I2C_STATUS 0x52 //get I2C status 69 | #define CH34x_I2C_COMMAND 0x53 //send I2C command 70 | 71 | #define CH34x_BUF_CLEAR 0xB2 //clear uncompleted data 72 | #define CH34x_I2C_CMD_X 0x54 //send I2C command 73 | #define CH34x_DELAY_MS 0x5E 74 | #define VENDOR_VERSION 0x5F //get version of chip 75 | 76 | #define CH34x_PARA_CMD_R0 0xAC //read data0 from Para 77 | #define CH34x_PARA_CMD_R1 0xAD //read data1 from Para 78 | #define CH34x_PARA_CMD_W0 0xA6 //write data0 to Para 79 | #define CH34x_PARA_CMD_W1 0xA7 //write data1 to Para 80 | #define CH34x_PARA_CMD_STS 0xA0 //get status of Para 81 | 82 | 83 | //CH341 COMMAND 84 | #define CH34x_CMD_SET_OUTPUT 0xA1 //set Para output 85 | #define CH34x_CMD_IO_ADDR 0xA2 //MEM IO Addr 86 | #define CH34x_CMD_PRINT_OUT 0xA3 //print output 87 | #define CH34X_CMD_SPI_STREAM 0xA8 //SPI command 88 | #define CH34x_CMD_SIO_STREAM 0xA9 //SIO command 89 | #define CH34x_CMD_I2C_STREAM 0xAA //I2C command 90 | #define CH34x_CMD_UIO_STREAM 0xAB //UIO command 91 | 92 | #define CH341A_CMD_UIO_STM_IN 0x00 // UIO Interface In ( D0 ~ D7 ) 93 | #define CH341A_CMD_UIO_STM_DIR 0x40 // UIO interface Dir( set dir of D0~D5 ) 94 | #define CH341A_CMD_UIO_STM_OUT 0x80 // UIO Interface Output(D0~D5) 95 | #define CH341A_CMD_UIO_STM_US 0xC0 // UIO Interface Delay Command( us ) 96 | #define CH341A_CMD_UIO_STM_END 0x20 // UIO Interface End Command 97 | 98 | //Single read/write the MAX number of blocks in EPP/MEM 99 | #define CH34x_EPP_IO_MAX ( CH34x_PACKET_LENGTH - 1 ) 100 | //CH341A 101 | #define CH34xA_EPP_IO_MAX 0xFF 102 | 103 | //request 104 | #define CH34x_DEBUG_READ 0x95 //read two regs 105 | #define CH34x_DEBUG_WRITE 0x9A //write two regs 106 | 107 | #define REQUEST_TYPE_READ ( USB_DIR_IN |USB_TYPE_VENDOR | USB_RECIP_OTHER ) 108 | #define REQUEST_TYPE_WRITE ( USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_OTHER) 109 | 110 | //Ioctl cmd Codes 111 | #define CH34x_GET_DRV_VERSION 0x00000001 112 | #define CH34x_CHIP_VERSION 0x00000003 113 | #define CH34x_FUNCTION_SETPARA_MODE 0x00000004 114 | #define CH34x_FUNCTION_READ_MODE 0x00000005 115 | #define CH34x_FUNCTION_WRITE_MODE 0x00000006 116 | #define CH34x_I2C_READ_MODE 0x00000007 117 | #define CH34x_I2C_WRITE_MODE 0x00000008 118 | #define CH34x_PIPE_DATA_DOWN 0x00000009 119 | #define CH34x_PIPE_WRITE_READ 0x0000000a 120 | #define CH34x_PIPE_DEVICE_CTRL 0x0000000b 121 | 122 | 123 | static unsigned char Read_Mode; //Read Data Pipe Mode From Para 124 | static unsigned char Write_Mode; //Write Data Pipe Mode From Para 125 | 126 | struct ch34x_pis{ 127 | struct usb_device *udev; /*the usb device for this device*/ 128 | struct usb_interface *interface; /*the interface for this device*/ 129 | struct usb_endpoint_descriptor *interrupt_in_endpoint; 130 | 131 | size_t interrupt_in_size; /*the size of rec data (interrupt)*/ 132 | unsigned char *interrupt_in_buffer; /*the buffer of rec data (interface)*/ 133 | struct urb *interrupt_in_urb; 134 | 135 | size_t bulk_in_size; /*the size of rec data (bulk)*/ 136 | unsigned char *bulk_in_buffer; /*the buffer of rec data (bulk)*/ 137 | struct urb *read_urb; /*the urb of bulk_in*/ 138 | __u8 bulk_in_endpointAddr; /*bulk input endpoint*/ 139 | __u8 bulk_out_endpointAddr; /*bulk output endpoint*/ 140 | unsigned char *bulk_out_buffer; 141 | 142 | struct semaphore limit_sem; /*semaphore*/ 143 | struct usb_anchor submitted; /*usb anchor */ 144 | 145 | unsigned long VenIc; /*Chip Version(CH341A : 0x0030)*/ 146 | int errors; 147 | int open_count; /*count the number of openers*/ 148 | spinlock_t err_lock; 149 | struct kref kref; 150 | }; 151 | 152 | static struct usb_driver ch34x_pis_driver; 153 | static void skel_delete( struct kref *kref ); 154 | 155 | 156 | static DEFINE_MUTEX( io_mutex ); 157 | 158 | /*usb VID/PID Register Into System*/ 159 | static struct usb_device_id ch34x_usb_ids[] = 160 | { 161 | { USB_DEVICE(CH34x_VENDOR_ID, CH34x_PRODUCT_ID) }, 162 | { } 163 | }; 164 | 165 | MODULE_DEVICE_TABLE(usb, ch34x_usb_ids); 166 | 167 | static int ch34x_fops_release(struct inode *inode, struct file *file) 168 | { 169 | struct ch34x_pis *dev; 170 | 171 | dev = (struct ch34x_pis *)file->private_data; 172 | if( dev == NULL ) 173 | return -ENODEV; 174 | 175 | mutex_lock( &io_mutex ); 176 | 177 | if( !--dev->open_count && dev->interface ) 178 | usb_autopm_put_interface( dev->interface ); 179 | mutex_unlock( &io_mutex ); 180 | 181 | kref_put( &dev->kref, skel_delete ); 182 | return 0; 183 | 184 | } 185 | 186 | //Control Endpoint Read 187 | static int ch34x_func_read( __u8 request, __u16 value, __u16 index, 188 | struct ch34x_pis *dev, unsigned char *buf, __u16 len) 189 | { 190 | int retval; 191 | /*Control Transform -->usb_control_msg */ 192 | retval = usb_control_msg( dev->udev, usb_rcvctrlpipe( dev->udev, 0 ), 193 | request, VENDOR_READ_TYPE, value, index, buf, len, 1000); 194 | 195 | dbg( "VENDOR_READ_TYPE: 0x%x : 0x%x : 0x%x %d - %d", request, 196 | value, index, retval, len ); 197 | 198 | return retval; 199 | } 200 | 201 | //Control Endpoint Write 202 | //In order to set chip register 203 | static int ch34x_func_write( __u8 request, __u16 value, __u16 index, 204 | struct ch34x_pis *dev, unsigned char *buf, 205 | __u16 len ) 206 | { 207 | int retval; 208 | 209 | retval = usb_control_msg( dev->udev, 210 | usb_sndctrlpipe(dev->udev, 0), request, 211 | VENDOR_WRITE_TYPE, value, index, buf, len, 1000); 212 | 213 | dbg( "VENDOR_READ_TYPE: 0x%x : 0x%x : 0x%x %d - %d", request, 214 | value, index, retval, len ); 215 | 216 | return retval; 217 | } 218 | 219 | 220 | //Init Parallel Mode 221 | //iMode-> 00/01 EPP 222 | //iMode-> 02 MEM 223 | static int CH34xInitParallel( unsigned char iMode, struct ch34x_pis *dev ) 224 | { 225 | int retval; 226 | __u8 RequestType = VENDOR_WRITE_TYPE; 227 | __u8 Request = CH34x_PARA_INIT; 228 | __u16 Value = ( iMode << 8 )|( iMode < 0x00000100 ? 0x02 : 0x00 ); 229 | __u16 Index = 0; 230 | __u16 len = 0; 231 | retval = usb_control_msg( dev->udev, 232 | usb_sndctrlpipe(dev->udev, 0), Request, 233 | RequestType, Value, Index, NULL, len, 1000); 234 | 235 | return retval; 236 | } 237 | 238 | //usb_fill_bulk_urb cpmplete callback 239 | static void ch34x_write_bulk_callback( struct urb *urb ) 240 | { 241 | struct ch34x_pis *dev; 242 | 243 | dev = urb->context; 244 | 245 | if( urb->status ) 246 | { 247 | if( !( urb->status == -ENOENT || urb->status == -ECONNRESET ||urb->status == -ESHUTDOWN)) 248 | err("%s - nonzero write bulk status received: %d", __func__, urb->status ); 249 | spin_lock( &dev->err_lock ); 250 | dev->errors = urb->status; 251 | spin_unlock( &dev->err_lock ); 252 | } 253 | #if( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 35) ) 254 | usb_buffer_free( urb->dev, urb->transfer_buffer_length, 255 | urb->transfer_buffer, urb->transfer_dma ); 256 | #else 257 | usb_free_coherent( urb->dev, urb->transfer_buffer_length, 258 | urb->transfer_buffer, urb->transfer_dma ); 259 | #endif 260 | up( &dev->limit_sem ); 261 | } 262 | 263 | //EPP/MEM Read 264 | ssize_t ch34x_fops_read(struct file *file, char __user *to_user, 265 | size_t count, loff_t *file_pos) 266 | { 267 | struct ch34x_pis *dev; 268 | unsigned char mBuffer[4]; 269 | int retval, i; 270 | int j = 0; 271 | unsigned long bytes_read, mNewlen, Returnlen; 272 | unsigned long Bytes, totallen = 0; 273 | 274 | dev = (struct ch34x_pis *)file->private_data; 275 | if( count == 0 || count > MAX_BUFFER_LENGTH ) 276 | { 277 | return count; 278 | } 279 | bytes_read = ( dev->VenIc >= 0x20 )?( CH34xA_EPP_IO_MAX - 280 | (CH34xA_EPP_IO_MAX & ( CH34x_PACKET_LENGTH - 1 ))): CH34x_EPP_IO_MAX; 281 | 282 | mNewlen = count / bytes_read; 283 | mBuffer[0] = mBuffer[2] = Read_Mode; 284 | mBuffer[1] = ( unsigned char )bytes_read; 285 | mBuffer[3] = ( unsigned char )( count - mNewlen * bytes_read ); 286 | dbg("count %d,->bytes_read %d,->mNewlen %d,->mBuffer[0] %d,->[1] %d,->[2]%d,->[3]%d",count,bytes_read,mNewlen,mBuffer[0],mBuffer[1],mBuffer[2],mBuffer[3]); 287 | 288 | if( mBuffer[3] ) 289 | mNewlen++; 290 | mutex_lock( &io_mutex ); 291 | if( !dev->interface ) 292 | { 293 | retval = -ENODEV; 294 | goto exit; 295 | } 296 | mutex_unlock( &io_mutex ); 297 | 298 | 299 | dev->bulk_in_buffer = kmalloc( sizeof( unsigned char ) * count, GFP_KERNEL ); 300 | if( dev->bulk_in_buffer == NULL ) 301 | { 302 | err("bulk_in_buffer malloc error"); 303 | retval = -ENOMEM; 304 | goto exit; 305 | } 306 | for( i = 0; i < mNewlen; i++ ) 307 | { 308 | if( (i + 1) == mNewlen && mBuffer[3] ) 309 | { 310 | j = 2; 311 | Bytes = mBuffer[3]; 312 | } 313 | else 314 | { 315 | j = 0; 316 | Bytes = bytes_read; 317 | } 318 | mutex_lock( &io_mutex ); 319 | retval = usb_bulk_msg( dev->udev, usb_sndbulkpipe( dev->udev, 320 | dev->bulk_out_endpointAddr ), mBuffer + j, 0x02, NULL, 10000); 321 | if( retval ) 322 | { 323 | retval = -EFAULT; 324 | mutex_unlock( &io_mutex ); 325 | err("usb_bulk_msg out error"); 326 | goto exit; 327 | } 328 | mutex_unlock( &io_mutex ); 329 | mutex_lock( &io_mutex ); 330 | retval = usb_bulk_msg( dev->udev, usb_rcvbulkpipe( dev->udev, 331 | dev->bulk_in_endpointAddr ), 332 | dev->bulk_in_buffer + i * bytes_read, 333 | Bytes, &Returnlen, 10000 ); 334 | 335 | if( retval ) 336 | { 337 | retval = -EFAULT; 338 | mutex_unlock( &io_mutex ); 339 | err("usb_bulk_msg in error"); 340 | goto exit; 341 | } 342 | mutex_unlock( &io_mutex ); 343 | totallen += Returnlen; 344 | } 345 | 346 | if( copy_to_user( to_user, dev->bulk_in_buffer, totallen )) 347 | retval = -EFAULT; 348 | else 349 | retval = totallen; 350 | kfree( dev->bulk_in_buffer ); 351 | exit: 352 | return retval; 353 | } 354 | 355 | //EPP/MEM Write 356 | ssize_t ch34x_fops_write(struct file *file, const char __user *user_buffer, 357 | size_t count, loff_t *file_pos) 358 | { 359 | struct ch34x_pis *dev; 360 | int retval = 0; 361 | char *WriteBuf = NULL; 362 | char *buf; 363 | struct urb *urb = NULL; 364 | unsigned int i; 365 | unsigned long mLength, mNewlen, mReturn = 0; 366 | unsigned long write_size; 367 | 368 | dev = (struct ch34x_pis *)file->private_data; 369 | if( count == 0 ) 370 | goto exit; 371 | else if( count > MAX_BUFFER_LENGTH ) 372 | { 373 | err("Data Overlimited,Must Under MAX_BUFFER_LENGTH"); 374 | retval = -EFAULT; 375 | goto exit; 376 | } 377 | spin_lock_irq( &dev->err_lock ); 378 | if(( retval = dev->errors ) < 0 ) 379 | { 380 | dev->errors = 0; 381 | retval = ( retval == -EPIPE ) ? retval : -EIO; 382 | } 383 | spin_unlock_irq( &dev->err_lock ); 384 | if( retval < 0 ) 385 | goto exit; 386 | 387 | mNewlen = count / CH34x_EPP_IO_MAX; 388 | mLength = count - mNewlen * CH34x_EPP_IO_MAX; 389 | mNewlen *= CH34x_PACKET_LENGTH; 390 | buf = (char *)kmalloc( sizeof(unsigned char) * (mNewlen + mLength), GFP_KERNEL ); 391 | mutex_lock( &io_mutex ); 392 | for( i = 0; i < mNewlen; i += CH34x_PACKET_LENGTH ) 393 | { 394 | buf[i] = Write_Mode; 395 | memcpy( buf + i + 1, user_buffer + mReturn, CH34x_EPP_IO_MAX ); 396 | mReturn += CH34x_EPP_IO_MAX; 397 | } 398 | if( mLength ) 399 | { 400 | buf[i] = Write_Mode; 401 | memcpy( buf + i + 1, user_buffer + mReturn, mLength ); 402 | mNewlen += mLength + 1 ; 403 | } 404 | mutex_unlock( &io_mutex ); 405 | if( mNewlen > MAX_BUFFER_LENGTH ) 406 | { 407 | 408 | urb = usb_alloc_urb( 0, GFP_KERNEL ); 409 | if( !urb ) 410 | { 411 | return -ENOMEM; 412 | goto error; 413 | } 414 | write_size = MAX_BUFFER_LENGTH; 415 | #if( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 35) ) 416 | WriteBuf = usb_buffer_alloc( dev->udev, write_size, 417 | GFP_KERNEL, &urb->transfer_dma ); 418 | #else 419 | WriteBuf = usb_alloc_coherent( dev->udev, write_size, 420 | GFP_KERNEL, &urb->transfer_dma ); 421 | #endif 422 | 423 | if( !WriteBuf ) 424 | { 425 | retval = -ENOMEM; 426 | goto error; 427 | } 428 | 429 | if( copy_from_user( WriteBuf, buf, write_size )) 430 | { 431 | retval = -EFAULT; 432 | goto error; 433 | } 434 | 435 | mutex_lock( &io_mutex ); 436 | if( !dev->interface ) 437 | { 438 | mutex_unlock( &io_mutex ); 439 | retval = -ENOMEM; 440 | goto error; 441 | } 442 | 443 | usb_fill_bulk_urb( urb, dev->udev, usb_sndbulkpipe( dev->udev, 444 | dev->bulk_out_endpointAddr ), WriteBuf, write_size, 445 | ch34x_write_bulk_callback, dev ); 446 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 447 | 448 | usb_anchor_urb( urb, &dev->submitted ); 449 | 450 | retval = usb_submit_urb( urb, GFP_KERNEL ); 451 | mutex_unlock( &io_mutex ); 452 | if( retval ) 453 | { 454 | err("%s - failed submitting write urb,line:%d", 455 | __func__, __LINE__ ); 456 | goto error_unanchor; 457 | } 458 | usb_free_urb( urb ); 459 | mLength = mNewlen - MAX_BUFFER_LENGTH; 460 | } 461 | else 462 | mLength = mNewlen; 463 | write_size = mLength; 464 | 465 | urb = usb_alloc_urb( 0, GFP_KERNEL ); 466 | if( !urb ) 467 | { 468 | return -ENOMEM; 469 | goto error; 470 | } 471 | 472 | #if( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 35) ) 473 | WriteBuf = usb_buffer_alloc( dev->udev, write_size, 474 | GFP_KERNEL, &urb->transfer_dma ); 475 | #else 476 | WriteBuf = usb_alloc_coherent( dev->udev, write_size, 477 | GFP_KERNEL, &urb->transfer_dma ); 478 | #endif 479 | if( !WriteBuf ) 480 | { 481 | retval = -ENOMEM; 482 | goto error; 483 | } 484 | 485 | if( __copy_from_user( WriteBuf + ( mNewlen - mLength), (unsigned char __user*)buf + (mNewlen - mLength), mLength )) 486 | { 487 | retval = -EFAULT; 488 | dbg("copy_from_user error"); 489 | goto error; 490 | } 491 | mutex_lock( &io_mutex ); 492 | if( !dev->interface ) 493 | { 494 | mutex_unlock( &io_mutex ); 495 | retval = -ENOMEM; 496 | goto error; 497 | } 498 | /*initialize urb*/ 499 | usb_fill_bulk_urb( urb, dev->udev, usb_sndbulkpipe( dev->udev, 500 | dev->bulk_out_endpointAddr ), WriteBuf + (mNewlen - mLength), 501 | write_size, ch34x_write_bulk_callback, dev ); 502 | 503 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 504 | usb_anchor_urb( urb, &dev->submitted ); 505 | retval = usb_submit_urb( urb, GFP_KERNEL ); 506 | mutex_unlock( &io_mutex ); 507 | if( retval ) 508 | { 509 | err( "%s -failed to write submit urb,line:%d", 510 | __func__, __LINE__ ); 511 | goto error_unanchor; 512 | } 513 | 514 | usb_free_urb( urb ); 515 | kfree( buf ); 516 | return mNewlen; 517 | error_unanchor: 518 | usb_unanchor_urb( urb ); 519 | error: 520 | if( urb ) 521 | { 522 | #if( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 35) ) 523 | usb_buffer_free( dev->udev, write_size, WriteBuf, 524 | urb->transfer_dma ); 525 | #else 526 | usb_free_coherent( dev->udev, write_size, WriteBuf, 527 | urb->transfer_dma ); 528 | #endif 529 | usb_free_urb( urb ); 530 | } 531 | exit: 532 | return retval; 533 | 534 | } 535 | 536 | //Write Data for I2C/Flash 537 | static int ch34x_WriteData( unsigned long iLength, unsigned long iBuffer, 538 | struct ch34x_pis *dev) 539 | { 540 | unsigned char *WriteBuf = NULL; 541 | unsigned long length; 542 | struct urb *urb; 543 | int retval = 0; 544 | 545 | length = iLength; 546 | 547 | if( length <= 0 ) 548 | { 549 | goto exit; 550 | } 551 | if( down_interruptible( &dev->limit_sem )) 552 | { 553 | retval = -ERESTARTSYS; 554 | goto exit; 555 | } 556 | 557 | spin_lock_irq( &dev->err_lock ); 558 | if((retval = dev->errors ) < 0) 559 | { 560 | dev->errors = 0; 561 | retval = ( retval == -EPIPE ) ? retval : -EIO; 562 | } 563 | spin_unlock_irq( &dev->err_lock ); 564 | 565 | if( retval < 0 ) goto exit; 566 | urb = usb_alloc_urb( 0, GFP_KERNEL ); 567 | if( !urb ) 568 | { 569 | retval = -ENOMEM; 570 | goto error; 571 | } 572 | #if( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 35) ) 573 | WriteBuf = usb_buffer_alloc( dev->udev, length, 574 | GFP_KERNEL, &urb->transfer_dma ); 575 | #else 576 | WriteBuf = usb_alloc_coherent( dev->udev, length, 577 | GFP_KERNEL, &urb->transfer_dma ); 578 | #endif 579 | if( !WriteBuf ) 580 | { 581 | retval = -ENOMEM; 582 | goto error; 583 | } 584 | 585 | if( copy_from_user( WriteBuf, (long __user *)iBuffer, length )) 586 | { 587 | retval = -EFAULT; 588 | goto error; 589 | } 590 | 591 | mutex_lock( &io_mutex ); 592 | if( !dev->interface ) 593 | { 594 | mutex_unlock( &io_mutex ); 595 | retval = -ENODEV; 596 | goto error; 597 | } 598 | 599 | /* initialize the urb properly */ 600 | usb_fill_bulk_urb( urb, dev->udev, usb_sndbulkpipe( dev->udev, 601 | dev->bulk_out_endpointAddr ), WriteBuf, length, 602 | ch34x_write_bulk_callback, dev ); 603 | 604 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 605 | usb_anchor_urb( urb, &dev->submitted ); 606 | /* send the data out the bulk port */ 607 | retval = usb_submit_urb( urb, GFP_KERNEL ); 608 | mutex_unlock( &io_mutex ); 609 | if( retval ) 610 | { 611 | err("%s - failed to submit writing urb,error %d,line %d", 612 | __func__, retval, __LINE__ ); 613 | goto error_unanchor; 614 | } 615 | 616 | /*release our reference to this urb*/ 617 | usb_free_urb( urb ); 618 | return length; 619 | 620 | error_unanchor: 621 | usb_unanchor_urb( urb ); 622 | error: 623 | if( urb ) 624 | { 625 | #if( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 35) ) 626 | usb_buffer_free( dev->udev, length, WriteBuf, 627 | urb->transfer_dma ); 628 | #else 629 | usb_free_coherent( dev->udev, length, WriteBuf, 630 | urb->transfer_dma ); 631 | #endif 632 | usb_free_urb( urb ); 633 | } 634 | up( &dev->limit_sem ); 635 | exit: 636 | return retval; 637 | } 638 | 639 | 640 | static int ch34x_data_write_read( unsigned long iLength, unsigned long iBuffer, 641 | unsigned long oBuffer, struct ch34x_pis *dev ) 642 | { 643 | unsigned long length; // the length of iBuffer 644 | unsigned long totallen; 645 | int bytes_read; 646 | unsigned char *iBuf; // Input data 647 | unsigned char *oBuf; // Output data 648 | struct urb *iUrb; 649 | int i, mSave; // the number of data in a block 650 | int readtimes; 651 | int retval = 0; 652 | dbg("iLength is %d\n",iLength ); 653 | if( iLength < 8 || iLength > MAX_BUFFER_LENGTH + 8 ) 654 | { 655 | err(" The length input error"); 656 | retval = -EFAULT; 657 | goto exit; 658 | } 659 | iBuf = kmalloc( sizeof(unsigned char) * iLength, GFP_KERNEL ); 660 | retval = copy_from_user(iBuf, (char __user*)iBuffer, iLength); 661 | if( retval != 0 ) 662 | { 663 | err("copy error"); 664 | kfree( iBuf ); 665 | goto exit; 666 | } 667 | iLength -= 8; 668 | length = iLength; 669 | mSave = iBuf[iLength]; 670 | readtimes = iBuf[iLength + 4]; 671 | kfree( iBuf ); 672 | dbg("the number of a block %d,should read %d", mSave, readtimes); 673 | if( i * readtimes > MAX_BUFFER_LENGTH || mSave == 0 || readtimes == 0 ) 674 | { 675 | return -EFAULT; 676 | goto exit; 677 | } 678 | 679 | if( down_interruptible( &dev->limit_sem )) 680 | { 681 | return -ERESTARTSYS; 682 | goto exit; 683 | } 684 | spin_lock_irq( &dev->err_lock ); 685 | if((retval = dev->errors) < 0) 686 | { 687 | dev->errors = 0; 688 | retval = (retval == -EPIPE) ? retval : -EIO; 689 | } 690 | spin_unlock_irq( &dev->err_lock ); 691 | if( retval < 0 ) 692 | goto exit; 693 | 694 | iUrb = usb_alloc_urb( 0, GFP_KERNEL ); 695 | if( !iUrb ) 696 | { 697 | retval = -ENOMEM; 698 | goto error; 699 | } 700 | #if( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 35) ) 701 | iBuf = usb_buffer_alloc( dev->udev, length, 702 | GFP_KERNEL, &iUrb->transfer_dma ); 703 | #else 704 | iBuf = usb_alloc_coherent( dev->udev, length, 705 | GFP_KERNEL, &iUrb->transfer_dma ); 706 | #endif 707 | if( !iBuf ) 708 | { 709 | retval = -ENOMEM; 710 | goto error; 711 | } 712 | 713 | if( copy_from_user( iBuf, (char __user *)iBuffer, length )) 714 | { 715 | retval = -EFAULT; 716 | goto exit; 717 | } 718 | mutex_lock( &io_mutex ); 719 | if( !dev->interface ) 720 | { 721 | mutex_unlock( &io_mutex ); 722 | retval = -ENODEV; 723 | goto error; 724 | } 725 | usb_fill_bulk_urb( iUrb, dev->udev, usb_sndbulkpipe( dev->udev, 726 | dev->bulk_out_endpointAddr ), iBuf, length, 727 | ch34x_write_bulk_callback, dev ); 728 | iUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 729 | usb_anchor_urb( iUrb, &dev->submitted ); 730 | retval = usb_submit_urb( iUrb, GFP_KERNEL ); 731 | mutex_unlock( &io_mutex ); 732 | if( retval ) 733 | { 734 | err("%s-failed submitting write urb in write_read", __func__); 735 | goto error_unanchor; 736 | } 737 | usb_free_urb( iUrb ); 738 | // Read Urb Data 739 | totallen = mSave * readtimes; 740 | dbg("mSave : %d, readtimes : %d, totallen : %d\n", mSave, readtimes, totallen); 741 | oBuf = kmalloc( sizeof( unsigned char ) * totallen, GFP_KERNEL ); 742 | totallen = 0; 743 | for( i = 0; i < readtimes; i++ ) 744 | { 745 | mutex_lock( &io_mutex ); 746 | retval = usb_bulk_msg( dev->udev, 747 | usb_rcvbulkpipe( dev->udev, dev->bulk_in_endpointAddr), 748 | oBuf + i * CH34x_EPP_IO_MAX, CH34x_EPP_IO_MAX, &bytes_read, 10000); 749 | 750 | totallen += bytes_read; 751 | mutex_unlock( &io_mutex ); 752 | } 753 | dbg("The actual length of Read is %d", totallen); 754 | /*if the read is sucessful,copy the data to userspace*/ 755 | if( copy_to_user((char __user *)oBuffer, oBuf, totallen)) 756 | { 757 | retval = -ENOMEM; 758 | kfree( oBuf ); 759 | goto exit; 760 | } 761 | 762 | kfree( oBuf ); 763 | return totallen; 764 | error_unanchor: 765 | if( iUrb ) 766 | usb_unanchor_urb( iUrb ); 767 | error: 768 | if( iUrb ) 769 | { 770 | #if( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 35) ) 771 | usb_buffer_free( dev->udev, length, iBuf, 772 | iUrb->transfer_dma ); 773 | #else 774 | usb_free_coherent( dev->udev, length, iBuf, 775 | iUrb->transfer_dma ); 776 | #endif 777 | usb_free_urb( iUrb ); 778 | } 779 | up( &dev->limit_sem ); 780 | exit: 781 | return retval; 782 | 783 | } 784 | 785 | static void skel_delete( struct kref *kref ) 786 | { 787 | struct ch34x_pis *dev = container_of( kref, struct ch34x_pis, kref ); 788 | usb_put_dev( dev->udev ); 789 | 790 | kfree( dev ); 791 | } 792 | 793 | int ch34x_fops_open(struct inode *inode, struct file *file) 794 | { 795 | struct ch34x_pis *ch34x_p; 796 | struct usb_interface *interface; 797 | int retval = 0; 798 | unsigned int subminor; 799 | 800 | #if( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 35) ) 801 | subminor = iminor( inode ); 802 | #else 803 | subminor = iminor( file->f_path.dentry->d_inode ); 804 | #endif 805 | 806 | interface = usb_find_interface( &ch34x_pis_driver, subminor ); 807 | if ( !interface ) 808 | { 809 | err( "%s-error,cannot find device for minor :%d", 810 | __func__, subminor); 811 | retval = -ENODEV; 812 | goto exit; 813 | } 814 | 815 | ch34x_p = usb_get_intfdata( interface ); 816 | if( !ch34x_p ) 817 | { 818 | err("Get interface data error"); 819 | retval = -ENODEV; 820 | goto exit; 821 | } 822 | 823 | /* add the usage for device*/ 824 | kref_get( &ch34x_p->kref ); 825 | 826 | mutex_lock( &io_mutex ); 827 | if( !ch34x_p->open_count++ ) 828 | { 829 | retval = usb_autopm_get_interface( interface ); 830 | if( retval ) 831 | { 832 | ch34x_p->open_count--; 833 | mutex_unlock( &io_mutex ); 834 | kref_put( &ch34x_p->kref, skel_delete ); 835 | goto exit; 836 | } 837 | } 838 | 839 | file->private_data = ch34x_p; 840 | mutex_unlock( &io_mutex ); 841 | 842 | exit: 843 | return retval; 844 | } 845 | 846 | #if( LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) ) 847 | int ch34x_fops_ioctl( struct inode *inode, struct file *file, 848 | unsigned int ch34x_cmd, unsigned long ch34x_arg ) 849 | #else 850 | long ch34x_fops_ioctl( struct file *file, unsigned int ch34x_cmd, 851 | unsigned long ch34x_arg ) 852 | #endif 853 | { 854 | int err = 0; 855 | int retval = 0; 856 | char buf[2]; 857 | unsigned long bytes_read; 858 | unsigned long bytes_write; 859 | char *drv_version_tmp = DRV_VERSION; 860 | struct ch34x_pis *ch34x_pis_tmp; 861 | 862 | ch34x_pis_tmp = ( struct ch34x_pis *)file->private_data; 863 | if( ch34x_pis_tmp == NULL ) 864 | { 865 | return -ENODEV; 866 | } 867 | switch( ch34x_cmd ) 868 | { 869 | case CH34x_GET_DRV_VERSION: 870 | { 871 | retval = copy_to_user( (char __user *)( ch34x_arg ), 872 | ( char * )drv_version_tmp, strlen( DRV_VERSION )); 873 | dbg("CH34x_GET_DRV_VERSION Successed"); 874 | break; 875 | } 876 | case CH34x_CHIP_VERSION: 877 | { 878 | retval = ch34x_func_read( VENDOR_VERSION, 879 | 0x0000, 0x0000, ch34x_pis_tmp, buf, 0x02 ); 880 | 881 | retval = copy_to_user( (char __user *)( ch34x_arg ), 882 | (char *)buf, 0x02 ); 883 | ch34x_pis_tmp->VenIc = buf[1] << 8 | buf[0]; 884 | dbg("------> 2 Chip Version is sucessful 0x%02x%x", buf[1],buf[0]); 885 | break; 886 | } 887 | case CH34x_FUNCTION_SETPARA_MODE: 888 | { 889 | retval = ch34x_func_write(CH34x_DEBUG_WRITE, 0x2525, 890 | (unsigned short)( ch34x_arg << 8 | ch34x_arg ), 891 | ch34x_pis_tmp, NULL, 0x00 ); 892 | if( retval != 0 ) 893 | err("CH34x_FUNCTION_SETPARA_MODE Error"); 894 | dbg("------>SetParaMode - ch34x_arg %x", ch34x_arg); 895 | break; 896 | } 897 | case CH34x_FUNCTION_READ_MODE: 898 | { 899 | if( ch34x_arg ) 900 | Read_Mode = CH34x_PARA_CMD_R1; 901 | else 902 | Read_Mode = CH34x_PARA_CMD_R0; 903 | 904 | dbg( "---->Read_Mode : 0x%x", Read_Mode ); 905 | break; 906 | } 907 | case CH34x_FUNCTION_WRITE_MODE: 908 | { 909 | if( ch34x_arg ) 910 | Write_Mode = CH34x_PARA_CMD_W1; 911 | else 912 | Write_Mode = CH34x_PARA_CMD_W0; 913 | 914 | dbg( "Write_Mode : 0x%x", Write_Mode ); 915 | break; 916 | } 917 | case CH34x_I2C_READ_MODE: 918 | { 919 | break; 920 | } 921 | case CH34x_I2C_WRITE_MODE: 922 | { 923 | break; 924 | } 925 | case CH34x_PIPE_DATA_DOWN: 926 | { 927 | dbg("------> Use Pipe Data Down"); 928 | retval = get_user( bytes_write, (long __user *)(*((long *)ch34x_arg))); 929 | dbg("------> length :%d",bytes_write); 930 | retval = ch34x_WriteData( bytes_write, 931 | (unsigned long)*(((long *)ch34x_arg) + 1), 932 | ch34x_pis_tmp ); 933 | 934 | break; 935 | } 936 | case CH34x_PIPE_WRITE_READ: 937 | { 938 | unsigned long addr; 939 | dbg("------> Use Pipe Date Write/Read"); 940 | dbg("Input number is %d\n",*((long *)ch34x_arg)); 941 | addr = (unsigned long)*(((long *)ch34x_arg) + 1 ); 942 | bytes_read = ch34x_data_write_read( *((unsigned long *)ch34x_arg), 943 | (unsigned long)*(((long *)ch34x_arg) + 1), 944 | *(((long *)ch34x_arg) + 2),ch34x_pis_tmp ); 945 | if( bytes_read <= 0 ) 946 | { 947 | err("Read Error"); 948 | return -EFAULT; 949 | } 950 | dbg("Read bytes is %d", bytes_read); 951 | retval = put_user( bytes_read, (long __user *)(*(((long *)ch34x_arg) + 3))); 952 | 953 | break; 954 | } 955 | case CH34x_PIPE_DEVICE_CTRL: 956 | { 957 | retval = CH34xInitParallel( (unsigned char)ch34x_arg, ch34x_pis_tmp ); 958 | if( retval < 0 ) 959 | { 960 | err("Init Parallel Error"); 961 | return -EFAULT; 962 | } 963 | break; 964 | } 965 | default: 966 | return -ENOTTY; 967 | break; 968 | } 969 | 970 | 971 | return 0; 972 | } 973 | 974 | static const struct file_operations ch34x_fops_driver = { 975 | .owner = THIS_MODULE, 976 | .open = ch34x_fops_open, 977 | .release = ch34x_fops_release, 978 | .read = ch34x_fops_read, 979 | .write = ch34x_fops_write, 980 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)) 981 | .ioctl = ch34x_fops_ioctl, 982 | #else 983 | .unlocked_ioctl = ch34x_fops_ioctl, 984 | #endif 985 | }; 986 | 987 | /* 988 | *usb class driver info in order to get a minor number from the usb core 989 | *and to have the device registered with the driver core 990 | */ 991 | static struct usb_class_driver ch34x_class = { 992 | .name = "ch34x_pis%d", 993 | .fops = &ch34x_fops_driver, 994 | .minor_base = CH34x_MINOR_BASE, 995 | }; 996 | 997 | static int ch34x_pis_probe( struct usb_interface *intf, const 998 | struct usb_device_id *id ) 999 | { 1000 | struct usb_host_interface *hinterface; 1001 | struct usb_endpoint_descriptor *endpoint; 1002 | struct ch34x_pis *ch34x_p; 1003 | 1004 | size_t buffer_size; 1005 | int retval = -ENOMEM; 1006 | int i; 1007 | 1008 | /* allocate memory for our device state and initialize it */ 1009 | ch34x_p = kzalloc( sizeof( *ch34x_p ), GFP_KERNEL ); 1010 | if( !ch34x_p ) 1011 | { 1012 | err("Out of Memory"); 1013 | goto error; 1014 | } 1015 | 1016 | /* init */ 1017 | kref_init( &ch34x_p->kref ); 1018 | sema_init( &ch34x_p->limit_sem, WRITES_IN_FLIGHT ); 1019 | spin_lock_init( &ch34x_p->err_lock ); 1020 | init_usb_anchor( &ch34x_p->submitted); 1021 | 1022 | ch34x_p->udev = usb_get_dev( interface_to_usbdev( intf )); 1023 | ch34x_p->interface = intf; 1024 | 1025 | hinterface = intf->cur_altsetting; 1026 | 1027 | if( hinterface->desc.bNumEndpoints < 1) 1028 | return -ENODEV; 1029 | /* Get Endpoint*/ 1030 | for( i = 0; i < hinterface->desc.bNumEndpoints; ++i ) 1031 | { 1032 | endpoint = &hinterface->endpoint[i].desc; 1033 | 1034 | if(( endpoint->bEndpointAddress & USB_DIR_IN ) && 1035 | ( endpoint->bmAttributes & 3 ) == 0x02 ) 1036 | { 1037 | dbg("Found a bulk in endpoint"); 1038 | buffer_size = le16_to_cpu( endpoint->wMaxPacketSize ); 1039 | ch34x_p->bulk_in_size = buffer_size; 1040 | ch34x_p->bulk_in_endpointAddr = endpoint->bEndpointAddress; 1041 | } 1042 | 1043 | if((( endpoint->bEndpointAddress & USB_DIR_IN ) == 0x00 ) && 1044 | ( endpoint->bmAttributes & 3 ) == 0x02 ) 1045 | { 1046 | dbg("Found a bulk out endpoint"); 1047 | ch34x_p->bulk_out_endpointAddr = endpoint->bEndpointAddress; 1048 | } 1049 | 1050 | if(( endpoint->bEndpointAddress & USB_DIR_IN ) && 1051 | ( endpoint->bmAttributes & 3 ) == 0x03 ) 1052 | { 1053 | dbg("Found a interrupt in endpoint"); 1054 | ch34x_p->interrupt_in_endpoint = endpoint; 1055 | } 1056 | } 1057 | 1058 | /* save our data point in this interface device */ 1059 | usb_set_intfdata( intf, ch34x_p ); 1060 | 1061 | retval = usb_register_dev( intf, &ch34x_class ); 1062 | if( retval ) 1063 | { 1064 | err( "usb_get_dev error,disable to use this device" ); 1065 | usb_set_intfdata( intf, NULL ); 1066 | goto error; 1067 | } 1068 | 1069 | dbg( "Ch34x_pis device now attached to ch34x_pis-%d", intf->minor ); 1070 | 1071 | return 0; 1072 | 1073 | error: 1074 | if( ch34x_p ) 1075 | kref_put( &ch34x_p->kref, skel_delete); 1076 | 1077 | return retval; 1078 | } 1079 | 1080 | static int ch34x_pis_suspend(struct usb_interface *intf, pm_message_t message ) 1081 | { 1082 | struct ch34x_pis *dev = usb_get_intfdata( intf ); 1083 | int time; 1084 | 1085 | if( !dev ) 1086 | return 0; 1087 | 1088 | time = usb_wait_anchor_empty_timeout( &dev->submitted, 1000 ); 1089 | if( !time ) 1090 | usb_kill_anchored_urbs( &dev->submitted ); 1091 | 1092 | return 0; 1093 | } 1094 | 1095 | static int ch34x_pis_resume( struct usb_interface *intf ) 1096 | { 1097 | return 0; 1098 | } 1099 | 1100 | static void ch34x_pis_disconnect( struct usb_interface *intf ) 1101 | { 1102 | struct ch34x_pis *dev; 1103 | int minor = intf->minor; 1104 | 1105 | dev = usb_get_intfdata( intf ); 1106 | usb_set_intfdata( intf, NULL ); 1107 | 1108 | /* give back our minor */ 1109 | usb_deregister_dev( intf, &ch34x_class ); 1110 | 1111 | mutex_lock( &io_mutex ); 1112 | dev->interface = NULL; 1113 | mutex_unlock( &io_mutex ); 1114 | 1115 | usb_kill_anchored_urbs( &dev->submitted ); 1116 | /*decrement our usage count*/ 1117 | kref_put( &dev->kref, skel_delete ); 1118 | 1119 | dbg("CH34x_pis-%d now disconnected", minor ); 1120 | } 1121 | 1122 | static int ch34x_pre_reset( struct usb_interface *intf ) 1123 | { 1124 | struct ch34x_pis *dev = usb_get_intfdata( intf ); 1125 | int time; 1126 | 1127 | mutex_lock( &io_mutex ); 1128 | time = usb_wait_anchor_empty_timeout( &dev->submitted, 1000 ); 1129 | if( !time ) 1130 | usb_kill_anchored_urbs( &dev->submitted ); 1131 | 1132 | return 0; 1133 | } 1134 | 1135 | static int ch34x_post_reset( struct usb_interface *intf ) 1136 | { 1137 | struct ch34x_pis *dev = usb_get_intfdata( intf ); 1138 | 1139 | dev->errors = -EPIPE; 1140 | mutex_unlock( &io_mutex ); 1141 | 1142 | return 0; 1143 | } 1144 | 1145 | //usb driver Interface 1146 | static struct usb_driver ch34x_pis_driver = { 1147 | .name = DRV_NAME, 1148 | .probe = ch34x_pis_probe, 1149 | .disconnect = ch34x_pis_disconnect, 1150 | .suspend = ch34x_pis_suspend, 1151 | .resume = ch34x_pis_resume, 1152 | .pre_reset = ch34x_pre_reset, 1153 | .post_reset = ch34x_post_reset, 1154 | .id_table = ch34x_usb_ids, 1155 | .supports_autosuspend = 1, 1156 | }; 1157 | 1158 | static int __init ch34x_pis_init(void) 1159 | { 1160 | int retval; 1161 | retval = usb_register( &ch34x_pis_driver ); 1162 | if( retval ) 1163 | printk( KERN_INFO "CH34x Device Register Failed.\n" ); 1164 | return retval; 1165 | } 1166 | 1167 | static void __exit ch34x_pis_exit(void) 1168 | { 1169 | usb_deregister(&ch34x_pis_driver); 1170 | } 1171 | 1172 | module_init(ch34x_pis_init); 1173 | module_exit(ch34x_pis_exit); 1174 | MODULE_AUTHOR("WCH TECH GRP"); 1175 | MODULE_DESCRIPTION("WCH CH34x Chip Driver"); 1176 | MODULE_LICENSE("GPL"); 1177 | -------------------------------------------------------------------------------- /CH341PAR_LINUX/demo/ch34x_lib.c: -------------------------------------------------------------------------------- 1 | // Created on: Nov 28, 2013 2 | /* 3 | * File : ch34x_lib.c ch34x_lib.h 4 | * 5 | ********************************************************************** 6 | *********** Copyright (C) WCH 2013.11.28 *************** 7 | *********** web: http://www.wch.cn *************** 8 | *********** AUTHOR: TECH33 (tech@wch.cn) *************** 9 | *********** Used for USB Interface Chip (CH341) *************** 10 | *********** Nanjing QinHeng Electronics Co.,Ltd *************** 11 | ********************************************************************** 12 | * 13 | * Running Environment: Linux 14 | * This file is used for CH34x in Epp/MEM/I2C/SPI 15 | * 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include //for 'ioctl' 23 | #include 24 | #include 25 | #include 26 | 27 | #include "ch34x_lib.h" 28 | 29 | #define CH34x_GET_DRV_VERSION 0x00000001 30 | #define CH34x_CHIP_VERSION 0x00000003 31 | #define CH34x_FUNCTION_SETPARA_MODE 0x00000004 32 | #define CH34x_FUNCTION_READ_MODE 0x00000005 33 | #define CH34x_FUNCTION_WRITE_MODE 0x00000006 34 | #define CH34x_I2C_READ_MODE 0x00000007 35 | #define CH34x_I2C_WRITE_MODE 0x00000008 36 | #define CH34x_PIPE_DATA_DOWN 0x00000009 37 | #define CH34x_PIPE_WRITE_READ 0x0000000a 38 | #define CH34x_PIPE_DEVICE_CTRL 0x0000000b 39 | 40 | 41 | int dev_fd; 42 | unsigned char VenIC; 43 | unsigned char StreamMode = 1; 44 | 45 | /* 46 | * ******************************************************************** 47 | * FUNCTION : Open Device 48 | * arg: 49 | * index : the number of device 50 | * ******************************************************************** 51 | */ 52 | int CH34xOpenDevice( UCHAR index ) 53 | { 54 | int retval = 0; 55 | char dev_path[20] = {'\0'}; 56 | memset( dev_path, 0, sizeof(dev_path)); 57 | sprintf( dev_path, "%s%c", "/dev/ch34x_pis", '0' + index); 58 | 59 | dev_fd = open( dev_path, O_RDWR ); 60 | if( dev_fd == -1 ) 61 | { 62 | printf("open /dev/ch34x_pis error, LINE : %d\n",__LINE__ ); 63 | return false; 64 | } 65 | // printf("Open successful\n"); 66 | 67 | return dev_fd; 68 | } 69 | 70 | /* 71 | * ******************************************************************** 72 | * FUNCTION : Close Device 73 | * ******************************************************************** 74 | */ 75 | void CH34xCloseDevice() 76 | { 77 | close( dev_fd ); 78 | } 79 | 80 | /* 81 | * ******************************************************************** 82 | * FUNCTION : Get Driver Version 83 | * arg: 84 | * drv_version : output buffer of driver version 85 | * ******************************************************************** 86 | */ 87 | BOOL CH34x_GetDrvVer( char *drv_version ) 88 | { 89 | int retval = 0; 90 | 91 | retval = ioctl( dev_fd, CH34x_GET_DRV_VERSION, (unsigned long)drv_version ); 92 | if( retval == -1 ) 93 | { 94 | printf( "CH34x_GET_DRV_VERSION function error line:%d\n", __LINE__ ); 95 | return false; 96 | } 97 | 98 | return true; 99 | } 100 | 101 | /* 102 | * ******************************************************************** 103 | * FUNCTION : Get Chip ID 104 | * arg: 105 | * VendorId : output data of chip version(CH341A : 0x0030) 106 | * ******************************************************************** 107 | */ 108 | BOOL CH34x_GetVendorId( PULONG VendorId ) 109 | { 110 | int retval = 0; 111 | retval = ioctl( dev_fd, CH34x_CHIP_VERSION, (unsigned long)VendorId); 112 | if( retval == -1 ) 113 | { 114 | printf("Get Chip Version Error,line:%d\n",__LINE__); 115 | return false; 116 | } 117 | 118 | VenIC = (UCHAR)*VendorId; 119 | // printf("VenIc is 0x%x\n",VenIC); 120 | return true; 121 | } 122 | 123 | //Mode = 0 ------>EPP Mode 124 | //Mode = 1 ------>EPP Mode 125 | //Mode = 2 ------>MEM Mode 126 | /* 127 | * ******************************************************************** 128 | * FUNCTION : Set Para Mode 129 | * arg: 130 | * Mode : set Para Mode( EPP or MEM ) 131 | * ******************************************************************** 132 | */ 133 | BOOL CH34xSetParaMode( ULONG Mode ) 134 | { 135 | int retval = 0; 136 | 137 | retval = ioctl( dev_fd, CH34x_FUNCTION_SETPARA_MODE, Mode); 138 | if( retval < 0 ) 139 | { 140 | printf("SetPara Error\n"); 141 | return false; 142 | } 143 | 144 | return true; 145 | } 146 | 147 | //Mode = 0 ------>EPP Mode 148 | //Mode = 1 ------>EPP Mode 149 | //Mode = 2 ------>MEM Mode 150 | /* 151 | * ******************************************************************** 152 | * FUNCTION : Init Para 153 | * arg: 154 | * Mode : first reset ,then set Para Mode( EPP or MEM ) 155 | * ******************************************************************** 156 | */ 157 | BOOL CH34xInitParallel( ULONG Mode ) 158 | { 159 | int retval = 0; 160 | 161 | retval = ioctl( dev_fd, CH34x_PIPE_DEVICE_CTRL, Mode); 162 | if( retval < 0 ) 163 | { 164 | printf("Init Parallel Error,LINE : %d\n", __LINE__); 165 | return false; 166 | } 167 | return true; 168 | } 169 | 170 | //PipeMode = 1 ------>Read from Pipe1 171 | //PipeMode = 0 ------>Read from Pipe0 172 | /* 173 | * ******************************************************************** 174 | * FUNCTION : EPP READ 175 | * arg: 176 | * oBuffer : Output buffer 177 | * ioLength: should read the length of Data/Addr 178 | * PipeMode: Read Pipe 179 | * -->0 Read Pipe0 Data 180 | * -->1 Read Pipe1 Addr 181 | * ******************************************************************** 182 | */ 183 | int CH34xEppRead( PUCHAR oBuffer, ULONG ioLength, ULONG PipeMode ) 184 | { 185 | int retval = 0; 186 | ULONG mReturnlen; 187 | retval = ioctl( dev_fd, CH34x_FUNCTION_READ_MODE, PipeMode ); 188 | if( retval < 0 ) 189 | { 190 | printf("Set Pipe Error\n"); 191 | return false; 192 | } 193 | mReturnlen = read( dev_fd, oBuffer, ioLength ); 194 | if( mReturnlen != ioLength ) 195 | { 196 | printf("Numbers of wanted output is not equal to input\n"); 197 | return false; 198 | } 199 | 200 | return mReturnlen; 201 | } 202 | 203 | //PipeMode = 1 ------>Read from Pipe1 204 | //PipeMode = 0 ------>Read from Pipe0 205 | /* 206 | * ******************************************************************** 207 | * FUNCTION : EPP Write 208 | * arg: 209 | * iBuffer : Iutput buffer 210 | * ioLength: should Write the length of Data/Addr 211 | * PipeMode: Write Pipe 212 | * -->0 Read Pipe0 Data 213 | * -->1 Read Pipe1 Addr 214 | * ******************************************************************** 215 | */ 216 | int CH34xEppWrite( PUCHAR iBuffer, ULONG ioLength, ULONG PipeMode ) 217 | { 218 | int retval =0; 219 | retval = ioctl( dev_fd, CH34x_FUNCTION_WRITE_MODE, PipeMode ); 220 | if( retval < 0 ) 221 | { 222 | printf("Set Write Pipe Error\n"); 223 | return false; 224 | } 225 | retval = write( dev_fd, iBuffer, ioLength ); 226 | if( retval < 0 ) 227 | { 228 | printf("Write Epp Error\n"); 229 | return false; 230 | } 231 | 232 | return true; 233 | } 234 | 235 | /* 236 | * ******************************************************************** 237 | * FUNCTION : EPP Write Data 238 | * arg: 239 | * iBuffer : Output buffer 240 | * ioLength: should Write the length of Data 241 | * ******************************************************************** 242 | */ 243 | int CH34xEppWriteData( PUCHAR iBuffer, ULONG ioLength ) 244 | { 245 | int retval; 246 | retval = CH34xEppWrite( iBuffer, ioLength, 0); 247 | if( !retval ) 248 | return false; 249 | return true; 250 | } 251 | 252 | /* 253 | * ******************************************************************** 254 | * FUNCTION : EPP Read Data 255 | * arg: 256 | * oBuffer : Iutput buffer 257 | * ioLength: should read the length of Data 258 | * ******************************************************************** 259 | */ 260 | int CH34xEppReadData( PUCHAR oBuffer, ULONG ioLength ) 261 | { 262 | int retval; 263 | retval = CH34xEppRead( oBuffer, ioLength, 0 ); // set Pipe0,then Read Data from pipe0 264 | if( !retval ) 265 | return false; 266 | return retval; 267 | } 268 | 269 | /* 270 | * ******************************************************************** 271 | * FUNCTION : EPP Write Addr 272 | * arg: 273 | * iBuffer : Output buffer Data 274 | * ioLength: should write the length of Addr 275 | * ******************************************************************** 276 | */ 277 | int CH34xEppWriteAddr( PUCHAR iBuffer, ULONG ioLength ) 278 | { 279 | int retval; 280 | retval = CH34xEppWrite( iBuffer, ioLength, 1 ); // set Pipe1,then Write Data from pipe1 281 | if( !retval ) 282 | return false; 283 | return true; 284 | } 285 | 286 | /* 287 | * ******************************************************************** 288 | * FUNCTION : EPP Read Addr 289 | * arg: 290 | * oBuffer : Iutput buffer Data 291 | * ioLength: should read the length of Addr 292 | * ******************************************************************** 293 | */ 294 | int CH34xEppReadAddr( PUCHAR oBuffer, ULONG ioLength ) 295 | { 296 | int retval; 297 | retval = CH34xEppRead( oBuffer, ioLength, 1 ); // set Pipe1,then Read Data from pipe1 298 | if( !retval ) 299 | return false; 300 | return retval; 301 | } 302 | 303 | /* 304 | * ******************************************************************** 305 | * FUNCTION : EPP Set Addr 306 | * arg: 307 | * iAddr: Need set the iAddr 308 | * ******************************************************************** 309 | */ 310 | int CH34xEppSetAddr( ULONG iAddr ) 311 | { 312 | int retval; 313 | UCHAR iBuffer[4]; 314 | ULONG mLength; 315 | iBuffer[0] = iAddr; 316 | mLength = 1; 317 | retval = CH34xEppWriteAddr( iBuffer, mLength ); 318 | if( !retval ) 319 | return false; 320 | 321 | return true; 322 | } 323 | 324 | /* 325 | * ******************************************************************** 326 | * FUNCTION : Init MEM 327 | * ******************************************************************** 328 | */ 329 | BOOL CH34xInitMEM(void) 330 | { 331 | int retval = 0; 332 | ULONG iMode; 333 | iMode = 0x02; 334 | retval = CH34xInitParallel( iMode ); 335 | if( retval == false ) 336 | { 337 | printf("Init MEM Mode Error\n"); 338 | return false; 339 | } 340 | return true; 341 | } 342 | 343 | //PipeMode = 1 ------>Read from Pipe1 344 | //PipeMode = 0 ------>Read from Pipe0 345 | /* 346 | * ******************************************************************** 347 | * FUNCTION : MEM Read 348 | * arg: 349 | * oBuffer : Output buffer 350 | * ioLength: should Read the length of Data 351 | * PipeMode: Write Pipe 352 | * -->0 Read Pipe0 Data 353 | * -->1 Read Pipe1 Data 354 | * ******************************************************************** 355 | */ 356 | int CH34xMEMReadData( PUCHAR oBuffer, ULONG ioLength, ULONG PipeMode ) 357 | { 358 | int retval = 0; 359 | ULONG mReturnlen; 360 | retval = ioctl( dev_fd, CH34x_FUNCTION_READ_MODE, PipeMode ); 361 | if( retval < 0 ) 362 | { 363 | printf("Set Pipe Error\n"); 364 | return false; 365 | } 366 | mReturnlen = read( dev_fd, oBuffer, ioLength ); 367 | if( mReturnlen != ioLength ) 368 | { 369 | printf("Numbers of wanted output is not equal to input\n"); 370 | return false; 371 | } 372 | 373 | return mReturnlen; 374 | } 375 | 376 | //PipeMode = 1 ------>Read from Pipe1 377 | //PipeMode = 0 ------>Read from Pipe0 378 | /* 379 | * ******************************************************************** 380 | * FUNCTION : MEM Write 381 | * arg: 382 | * iBuffer : Iutput buffer 383 | * ioLength: should Write the length of Data 384 | * PipeMode: Write Pipe 385 | * -->0 Read Pipe0 Data 386 | * -->1 Read Pipe1 Data 387 | * ******************************************************************** 388 | */ 389 | int CH34xMEMWriteData( PUCHAR iBuffer, ULONG ioLength, ULONG PipeMode ) 390 | { 391 | int retval =0; 392 | retval = ioctl( dev_fd, CH34x_FUNCTION_WRITE_MODE, PipeMode ); 393 | if( retval < 0 ) 394 | { 395 | printf("Set Write Pipe Error\n"); 396 | return false; 397 | } 398 | retval = write( dev_fd, iBuffer, ioLength ); 399 | if( retval < 0 ) 400 | { 401 | printf("Write Epp Error\n"); 402 | return false; 403 | } 404 | 405 | return true; 406 | } 407 | 408 | /* 409 | * ******************************************************************** 410 | * FUNCTION : Set Stream Mode 411 | * arg: 412 | * Mode : Set Stream Mode 413 | * -> bit0~1 : set I2C SCL rate 414 | * --> 00 : Low Rate /20KHz 415 | * --> 01 : Default Rate /100KHz 416 | * --> 10 : Fast Rate /400KHz 417 | * --> 11 : Full Rate /750KHz 418 | * -> bit2 : set spi mode 419 | * --> 0 : one in one out(D3 :clk/ D5 :out/ D7 :in) 420 | * --> 1 : two in two out(D3 :clk/ D4,D5 :out/ D6,D7 :in) 421 | * -> bit7 : set spi data mode 422 | * --> 0 : low bit first 423 | * --> 1 : high bit first 424 | * other bits must keep 0 425 | * ******************************************************************** 426 | */ 427 | BOOL CH34xSetStream( ULONG Mode ) 428 | { 429 | UCHAR mBuffer[CH341_PACKET_LENGTH]; 430 | ULONG mLength; 431 | if( VenIC < 0x20 ) 432 | return false; 433 | StreamMode = (UCHAR)( Mode & 0x8F ); 434 | mBuffer[0] = CH341A_CMD_I2C_STREAM; 435 | mBuffer[1] = CH341A_CMD_I2C_STM_SET; 436 | mBuffer[2] = CH341A_CMD_I2C_STM_END; 437 | mLength = 3; 438 | if( CH34xWriteData( mBuffer, &mLength )) 439 | { 440 | if( mLength >= 2 ) 441 | return true; 442 | } 443 | return false; 444 | } 445 | 446 | /* 447 | * ******************************************************************** 448 | * FUNCTION : Set Delay 449 | * arg: 450 | * iDelay : set delay time(ms) 451 | * ******************************************************************** 452 | */ 453 | BOOL CH34xSetDelaymS( ULONG iDelay ) 454 | { 455 | UCHAR mBuffer[CH341_PACKET_LENGTH]; 456 | ULONG mLength; 457 | if( VenIC < 0x20 ) 458 | return false; 459 | while( iDelay ) 460 | { 461 | mLength = iDelay >= CH341A_CMD_I2C_STM_DLY ? CH341A_CMD_I2C_STM_DLY : iDelay; 462 | iDelay -= mLength; 463 | mBuffer[0] = CH341A_CMD_I2C_STREAM; 464 | mBuffer[1] = (UCHAR)( CH341A_CMD_I2C_STM_MS | mLength ); 465 | mBuffer[2] = CH341A_CMD_I2C_STM_END; 466 | mLength = 3; 467 | if(( CH34xWriteData( mBuffer, &mLength )) == false ) 468 | return false; 469 | } 470 | return true; 471 | } 472 | 473 | //This is needless for the moment 474 | BOOL CH34xReadData( PVOID oBuffer, PULONG ioLength ) 475 | { 476 | UCHAR mBuffer[MAX_BUFFER_LENGTH]; 477 | ULONG mLength; 478 | } 479 | 480 | /* 481 | * ******************************************************************** 482 | * FUNCTION : Write Data ( for i2c/flash ) 483 | * arg: 484 | * iBuffer : should Input data buffer 485 | * ioLength : write length of data 486 | * ******************************************************************** 487 | */ 488 | BOOL CH34xWriteData( PVOID iBuffer, PULONG ioLength ) 489 | { 490 | int retval = 0; 491 | int i=0; 492 | unsigned long mLen; 493 | struct{ 494 | ULONG length; 495 | PUCHAR ByteBuffer; 496 | }Write; 497 | if( *ioLength > MAX_BUFFER_LENGTH ) 498 | *ioLength = MAX_BUFFER_LENGTH; 499 | mLen = *ioLength; 500 | Write.length = ioLength; 501 | Write.ByteBuffer = (PUCHAR)malloc( sizeof( unsigned char ) * mLen ); 502 | memcpy( Write.ByteBuffer, (PUCHAR)iBuffer, mLen ); 503 | printf("ByteBuffer:"); 504 | for(i=0;i:%p\n",Read.iBuf); 555 | Read.oReadlen = iWriteLength; 556 | retval = ioctl( dev_fd, CH34x_PIPE_WRITE_READ, (unsigned long)&Read ); 557 | if( retval == -1 ) 558 | { 559 | printf("Error in pipe write/read\n"); 560 | return false; 561 | } 562 | return true; 563 | } 564 | 565 | 566 | /* 567 | * ******************************************************************** 568 | * FUNCTION : Set direction and output data of CH341 569 | * arg: 570 | * Data : Control direction and data 571 | 572 | * iEnbale : set direction and data enable 573 | * --> Bit16 High : effect on Bit15~8 of iSetDataOut 574 | * --> Bit17 High : effect on Bit15~8 of iSetDirOut 575 | * --> Bit18 High : effect on Bit7~0 of iSetDataOut 576 | * --> Bit19 High : effect on Bit7~0 of iSetDirOut 577 | * --> Bit20 High : effect on Bit23~16 of iSetDataOut 578 | * iSetDirOut : set io direction 579 | * -- > Bit High : Output 580 | * -- > Bit Low : Input 581 | * iSetDataOut : set io data 582 | * Output: 583 | * -- > Bit High : High level 584 | * -- > Bit Low : Low level 585 | * Note: 586 | * Bit7~Bit0<==>D7-D0 587 | * Bit8<==>ERR# Bit9<==>PEMP Bit10<==>INT# Bit11<==>SLCT Bit13<==>WAIT# Bit14<==>DATAS#/READ# Bit15<==>ADDRS#/ADDR/ALE 588 | * The pins below can only be used in output mode: 589 | * Bit16<==>RESET# Bit17<==>WRITE# Bit18<==>SCL Bit29<==>SDA 590 | * ******************************************************************** 591 | */ 592 | 593 | BOOL CH34xSetOutput( ULONG iEnable, ULONG iSetDirOut, ULONG iSetDataOut) 594 | { 595 | ULONG mLength; 596 | UCHAR mBuffer[32]; 597 | mBuffer[0] = CH341A_CMD_SET_OUTPUT; 598 | mBuffer[1] = 0x6A; 599 | mBuffer[2] = (UCHAR)( iEnable & 0x1F ); 600 | mBuffer[3] = (UCHAR)( iSetDataOut >> 8 & 0xEF ); 601 | mBuffer[4] = (UCHAR)( iSetDirOut >> 8 & 0xEF | 0x10 ); 602 | mBuffer[5] = (UCHAR)( iSetDataOut & 0xFF ); 603 | mBuffer[6] = (UCHAR)( iSetDirOut & 0xFF ); 604 | mBuffer[7] = (UCHAR)( iSetDataOut >> 16 & 0x0F ); 605 | mBuffer[8] = 0; 606 | mBuffer[9] = 0; 607 | mBuffer[10] = 0; 608 | mLength = 11; 609 | if ( CH34xWriteData( mBuffer, &mLength ) ) { //Write Data 610 | if ( mLength >= 8 ) return( true); 611 | } 612 | return( false); 613 | } 614 | 615 | 616 | /* 617 | * ******************************************************************** 618 | * FUNCTION : Set direction and output data of D5-D0 on CH341 619 | * arg: 620 | * Data : Control direction and data 621 | * iSetDirOut : set io direction 622 | * -- > Bit High : Output 623 | * -- > Bit Low : Input 624 | * iSetDataOut : set io data 625 | * Output: 626 | * -- > Bit High : High level 627 | * -- > Bit Low : Low level 628 | * ******************************************************************** 629 | */ 630 | 631 | BOOL CH34xSet_D5_D0( UCHAR iSetDirOut,UCHAR iSetDataOut) 632 | { 633 | ULONG mLength; 634 | UCHAR mBuffer[32]; 635 | mBuffer[0] = CH341A_CMD_UIO_STREAM; 636 | mBuffer[1] = (UCHAR)( CH341A_CMD_UIO_STM_OUT | iSetDataOut & 0x3F ); 637 | mBuffer[2] = (UCHAR)( CH341A_CMD_UIO_STM_DIR | iSetDirOut & 0x3F ); 638 | mBuffer[3] = CH341A_CMD_UIO_STM_END; 639 | mLength = 4; 640 | if ( CH34xWriteData( mBuffer, &mLength ) ) { //Write Data 641 | if ( mLength >= 3 ) return( true ); 642 | } 643 | return( false); 644 | } 645 | 646 | 647 | 648 | 649 | /* 650 | * ******************************************************************** 651 | * FUNCTION : Write/Read I2C Data Stream 652 | * This function issue a set of packets of iWriteBuffer data 653 | * arg: 654 | * iWriteLength : should write the length of data 655 | * iWriteBuffer : input buffer 656 | * oReadLength : should read the length of data 657 | * oReadBuffer : output buffer 658 | * ******************************************************************** 659 | */ 660 | BOOL CH34xStreamI2C( ULONG iWriteLength, PVOID iWriteBuffer, 661 | ULONG iReadLength, PVOID oReadBuffer ) 662 | { 663 | UCHAR mBuffer[MAX_BUFFER_LENGTH]; 664 | ULONG i, j, mLength; 665 | PUCHAR mWrBuf; 666 | 667 | if( VenIC < 0x20 ) 668 | return false; 669 | mLength = max( iWriteLength, iReadLength ); 670 | if( mLength > MAX_BUFFER_LENGTH ) 671 | return false; 672 | if( mLength <= DEFAULT_BUFFER_LEN ) 673 | mWrBuf = (PVOID)mBuffer; 674 | else 675 | { 676 | mWrBuf = (PVOID)malloc( sizeof( UCHAR ) * MAX_BUFFER_LENGTH ); 677 | if( mWrBuf == NULL) 678 | return false; 679 | } 680 | i = 0; 681 | mWrBuf[i++] = CH341A_CMD_I2C_STREAM; 682 | if(( StreamMode & 0x03 ) == 0 ) 683 | { 684 | mWrBuf[i++] = CH341A_CMD_I2C_STM_US | 10; 685 | mWrBuf[i++] = CH341A_CMD_I2C_STM_US | 10; 686 | } 687 | mWrBuf[i++] = CH341A_CMD_I2C_STM_STA; 688 | if( iWriteLength ) 689 | { 690 | for( j = 0; j < iWriteLength; j++) 691 | { 692 | mLength = CH341_PACKET_LENGTH - i % CH341_PACKET_LENGTH; 693 | if( mLength <= 2 ) 694 | { 695 | while( mLength-- ) 696 | mWrBuf[i++] = CH341A_CMD_I2C_STM_END; 697 | mLength = CH341_PACKET_LENGTH; 698 | } 699 | if( mLength >= CH341_PACKET_LENGTH ) 700 | { 701 | mWrBuf[i++] = CH341A_CMD_I2C_STREAM; 702 | mLength = CH341_PACKET_LENGTH - 1; 703 | 704 | } 705 | mLength--; 706 | mLength--; 707 | if( mLength > iWriteLength - j) 708 | mLength = iWriteLength - j; 709 | mWrBuf[i++] = (UCHAR)(CH341A_CMD_I2C_STM_OUT | mLength); 710 | while( mLength-- ) 711 | mWrBuf[i++] = *((PUCHAR)iWriteBuffer + j++ ); 712 | } 713 | 714 | } 715 | if( iReadLength ) 716 | { 717 | mLength = CH341_PACKET_LENGTH - i % CH341_PACKET_LENGTH; 718 | if( mLength <= 3 ) 719 | { 720 | while( mLength-- ) 721 | mWrBuf[i++] = CH341A_CMD_I2C_STM_END; 722 | mLength = CH341_PACKET_LENGTH; 723 | } 724 | if( mLength >= CH341_PACKET_LENGTH ) 725 | mWrBuf[i++] = CH341A_CMD_I2C_STREAM; 726 | if( iWriteLength > 1 ) 727 | { 728 | mWrBuf[i++] = CH341A_CMD_I2C_STM_STA; 729 | mWrBuf[i++] = (UCHAR)(CH341A_CMD_I2C_STM_OUT | 1); 730 | mWrBuf[i++] = *(PUCHAR)iWriteBuffer | 0x01; 731 | } 732 | else if( iWriteLength ) 733 | { 734 | i--; 735 | mWrBuf[i++] = *(PUCHAR)iWriteBuffer | 0x01; 736 | } 737 | for( j = 1; j < iReadLength; ) 738 | { 739 | mLength = CH341_PACKET_LENGTH - i % CH341_PACKET_LENGTH; 740 | if( mLength <= 1) 741 | { 742 | if( mLength ) 743 | mWrBuf[i++] = CH341A_CMD_I2C_STM_END; 744 | mLength = CH341_PACKET_LENGTH; 745 | } 746 | if( mLength >= CH341_PACKET_LENGTH ) 747 | mWrBuf[i++] = CH341A_CMD_I2C_STREAM; 748 | mLength = iReadLength - j >= CH341_PACKET_LENGTH ? CH341_PACKET_LENGTH : iReadLength - j; 749 | mWrBuf[i++] = (UCHAR)(CH341A_CMD_I2C_STM_IN | mLength); 750 | j += mLength; 751 | if( mLength >= CH341_PACKET_LENGTH ) 752 | { 753 | mWrBuf[i] = CH341A_CMD_I2C_STM_END; 754 | i += CH341_PACKET_LENGTH - i % CH341_PACKET_LENGTH; 755 | } 756 | } 757 | mLength = CH341_PACKET_LENGTH - i % CH341_PACKET_LENGTH; 758 | if( mLength <= 1 ) 759 | { 760 | if( mLength) 761 | mWrBuf[i++] = CH341A_CMD_I2C_STM_END; 762 | mLength = CH341_PACKET_LENGTH; 763 | } 764 | if( mLength >= CH341_PACKET_LENGTH ) 765 | mWrBuf[i++] = CH341A_CMD_I2C_STREAM; 766 | mWrBuf[i++] = CH341A_CMD_I2C_STM_IN; 767 | } 768 | mLength = CH341_PACKET_LENGTH - i % CH341_PACKET_LENGTH; 769 | if( mLength <= 1 ) 770 | { 771 | if( mLength ) 772 | mWrBuf[i++] = CH341A_CMD_I2C_STM_END; 773 | mLength = CH341_PACKET_LENGTH; 774 | } 775 | if( mLength >= CH341_PACKET_LENGTH ) 776 | mWrBuf[i++] = CH341A_CMD_I2C_STREAM; 777 | mWrBuf[i++] = CH341A_CMD_I2C_STM_STO; 778 | mWrBuf[i++] = CH341A_CMD_I2C_STM_END; 779 | mLength = 0; 780 | if( iReadLength ) 781 | { 782 | mWrBuf[i] = CH341_PACKET_LENGTH; 783 | mWrBuf[i+4] = (iReadLength + CH341_PACKET_LENGTH -1)/CH341_PACKET_LENGTH; 784 | i = i + 8; 785 | } 786 | if( iReadLength ) 787 | { 788 | j = CH34xWriteRead( i, mWrBuf, &mLength, oReadBuffer ); 789 | if( mLength != iReadLength ) 790 | { 791 | printf("Return length is not equal to input length\n"); 792 | j = false; 793 | } 794 | } 795 | else 796 | j = CH34xWriteData( mWrBuf, &i); 797 | 798 | // printf("Return mLength is %d\n", mLength); 799 | if( max( iWriteLength, iReadLength ) >= DEFAULT_BUFFER_LEN ) 800 | free( mWrBuf ); 801 | 802 | return ( j ); 803 | } 804 | 805 | /* 806 | * ******************************************************************** 807 | * FUNCTION : Read EEPROM Data (For I2C) 808 | * arg: 809 | * iEepromID : EEPROM TYPE 810 | * iAddr : the start addr for read 811 | * iLength : should read the length of data 812 | * oBuffer : output buffer 813 | * ******************************************************************** 814 | */ 815 | BOOL CH34xReadEEPROM( EEPROM_TYPE iEepromID, ULONG iAddr, 816 | ULONG iLength, PUCHAR oBuffer ) 817 | { 818 | ULONG mLen; 819 | UCHAR mWrBuf[4]; 820 | 821 | if( iEepromID >= ID_24C01 && iEepromID <= ID_24C16 ) 822 | { 823 | while( iLength ) 824 | { 825 | mWrBuf[0] = (UCHAR)( 0xA0 | (iAddr >> 7) & 0x0E ); 826 | mWrBuf[1] = (UCHAR)iAddr; 827 | mLen = min( iLength, DEFAULT_BUFFER_LEN ); 828 | if( !CH34xStreamI2C( 2, mWrBuf, mLen, oBuffer )) 829 | return false; 830 | iAddr += mLen; 831 | iLength -= mLen; 832 | oBuffer += mLen; 833 | } 834 | } 835 | else if( iEepromID >= ID_24C32 && iEepromID <= ID_24C4096 ) 836 | { 837 | 838 | while( iLength ) 839 | { 840 | mWrBuf[0] = (UCHAR)( 0xA0 | (iAddr >> 15 ) & 0x0E ); 841 | mWrBuf[1] = (UCHAR)( iAddr >> 8 ); 842 | mWrBuf[2] = (UCHAR)iAddr; 843 | mLen = min( iLength, DEFAULT_BUFFER_LEN ); 844 | if( !CH34xStreamI2C( 3, mWrBuf, mLen, oBuffer )) 845 | return false; 846 | iAddr += mLen; 847 | iLength -= mLen; 848 | oBuffer += mLen; 849 | } 850 | } 851 | else 852 | return false; 853 | 854 | return true; 855 | } 856 | 857 | /* 858 | * ******************************************************************** 859 | * FUNCTION : Write EEPROM Data (For I2C) 860 | * arg: 861 | * iEepromID : EEPROM TYPE 862 | * iAddr : the start addr for read 863 | * iLength : should write the length of data 864 | * iBuffer : Iutput buffer 865 | * ******************************************************************** 866 | */ 867 | 868 | //Note : Sometimes you should set Delay time( CH34xSetDelaymS()) after 869 | // CH34xStreamI2C() 870 | BOOL CH34xWriteEEPROM( EEPROM_TYPE iEepromID, ULONG iAddr, 871 | ULONG iLength, PUCHAR iBuffer ) 872 | { 873 | ULONG mLen; 874 | UCHAR mWrBuf[256]; 875 | if( iEepromID >= ID_24C01 && iEepromID <= ID_24C16 ) 876 | { 877 | while( iLength ) 878 | { 879 | mWrBuf[0] = (UCHAR)( 0xA0 | ( iAddr >>7 ) & 0x0E); 880 | mWrBuf[1] = (UCHAR)iAddr; 881 | mLen = iEepromID >= ID_24C04 ? 16 - ( iAddr & 15 ) : 8 - (iAddr & 7 ); 882 | if( mLen > iLength ) 883 | mLen = iLength; 884 | memcpy( &mWrBuf[2], iBuffer, mLen ); 885 | if( !CH34xStreamI2C( 2 + mLen, mWrBuf, 0, NULL )) 886 | return false; 887 | iAddr += mLen; 888 | iLength -= mLen; 889 | iBuffer += mLen; 890 | } 891 | } 892 | else if( iEepromID >= ID_24C32 && iEepromID <= ID_24C4096 ) 893 | { 894 | printf("Addr is %d\n",iAddr); 895 | printf("iLength is %d\n",iLength); 896 | printf("iBuffer is %x\n",*iBuffer); 897 | while( iLength ) 898 | { 899 | mWrBuf[0] = (UCHAR)( 0xA0 | ( iAddr >>15 ) & 0x0E ); 900 | mWrBuf[1] = (UCHAR)( iAddr >> 8 ); 901 | mWrBuf[2] = (UCHAR)iAddr; 902 | mLen = iEepromID >= ID_24C512 ? 128 - ( iAddr & 127) : (iEepromID >= ID_24C128 ? 64 - ( iAddr & 63 ) : 32 - ( iAddr & 31)); 903 | if( mLen > iLength ) 904 | mLen = iLength; 905 | memcpy( &mWrBuf[3], iBuffer, mLen ); 906 | printf("mWrBuf[3] is %x\n",mWrBuf[3]); 907 | if( !CH34xStreamI2C( 3 + mLen, mWrBuf, 0, NULL )) 908 | return false; 909 | iAddr += mLen; 910 | iLength -= mLen; 911 | iBuffer += mLen; 912 | 913 | } 914 | } 915 | else 916 | return false; 917 | 918 | return true; 919 | 920 | } 921 | 922 | //Used for high bit transform 923 | const UCHAR mMsbTable[256] = { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 924 | 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, // 0XH 925 | 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 926 | 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, // 1XH 927 | 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 928 | 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, // 2XH 929 | 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 930 | 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, // 3XH 931 | 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 932 | 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, // 4XH 933 | 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 934 | 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, // 5XH 935 | 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 936 | 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, // 6XH 937 | 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 938 | 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, // 7XH 939 | 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 940 | 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, // 8XH 941 | 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 942 | 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, // 9XH 943 | 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 944 | 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, // AXH 945 | 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 946 | 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, // BXH 947 | 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 948 | 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, // CXH 949 | 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 950 | 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, // DXH 951 | 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 952 | 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, // EXH 953 | 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 954 | 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF }; // FXH 955 | 956 | /* 957 | * ******************************************************************** 958 | * FUNCTION : Write/Read Flash Data (For SPI) 959 | * arg: 960 | * iChipselect : Flash cs enable 961 | * iLength : the length of data 962 | * ioBuffer : one in one out buffer 963 | * ioBuffer2 : two in two out buffer 964 | * ******************************************************************** 965 | */ 966 | BOOL CH34xStreamSPIx( ULONG iChipselect, ULONG iLength, 967 | PVOID ioBuffer, PVOID ioBuffer2 ) 968 | { 969 | UCHAR mBuffer[DEFAULT_BUFFER_LEN]; 970 | ULONG i, j, mLength, mSelect, mCount,mReturn; 971 | PUCHAR mWrBuf; 972 | UCHAR c1, c2; 973 | mReturn = iLength; 974 | if( VenIC < 0x20 ) 975 | { 976 | printf("Not support this device\n"); 977 | return false; 978 | } 979 | if( iLength <= DEFAULT_BUFFER_LEN/2 ) 980 | { 981 | mWrBuf = (PVOID)mBuffer; 982 | i = DEFAULT_BUFFER_LEN; 983 | } 984 | else 985 | { 986 | mWrBuf = (PVOID)malloc( sizeof( UCHAR ) * MAX_BUFFER_LENGTH ); 987 | if( mWrBuf == NULL ) 988 | return false; 989 | i = MAX_BUFFER_LENGTH; 990 | } 991 | memset( mWrBuf, 0, sizeof( UCHAR ) * i ); 992 | i = 0; 993 | if( iChipselect & 0x80 ) 994 | { 995 | mWrBuf[i++] = CH341A_CMD_UIO_STREAM; 996 | switch( iChipselect & 0x03 ) 997 | { 998 | case 0x00: //DCK/D3->0, D0 ->0 999 | mSelect = 0x36; 1000 | break; 1001 | case 0x01: //DCK/D3->0, D1 ->0 1002 | mSelect = 0x35; 1003 | break; 1004 | case 0x02: //DCK/D3->0, D2 ->0 1005 | mSelect = 0x33; 1006 | break; 1007 | default: //DCK/D3->0, D4 ->0 1008 | mSelect = 0x27; 1009 | break; 1010 | } 1011 | 1012 | mWrBuf[i++] = (UCHAR)( CH341A_CMD_UIO_STM_OUT | mSelect );// Output data 1013 | mWrBuf[i++] = (UCHAR)( CH341A_CMD_UIO_STM_DIR | 0x3F ); // set D5~D0 direct 1014 | mWrBuf[i++] = CH341A_CMD_UIO_STM_END; 1015 | i = CH341_PACKET_LENGTH; 1016 | } 1017 | if( iLength ) 1018 | { 1019 | if( (ULONG)ioBuffer2 < 4 ) 1020 | { 1021 | for( j = 0; j < iLength; ) 1022 | { 1023 | mLength = CH341_PACKET_LENGTH - 1; 1024 | if( mLength > iLength - j ) 1025 | mLength = iLength - j; 1026 | mWrBuf[i++] = CH341A_CMD_SPI_STREAM; 1027 | if( StreamMode & 0x80 ) 1028 | { 1029 | while( mLength-- ) 1030 | mWrBuf[i++] = mMsbTable[*((PUCHAR)ioBuffer + j++)]; 1031 | } 1032 | else 1033 | while( mLength-- ) 1034 | mWrBuf[i++] = *((PUCHAR)ioBuffer + j++); 1035 | if( VenIC == 0x20 && i % CH341_PACKET_LENGTH == 0 ) 1036 | { 1037 | mWrBuf[i] = mWrBuf[i+1] = 0; 1038 | i += CH341_PACKET_LENGTH; 1039 | } 1040 | } 1041 | } 1042 | else 1043 | { 1044 | for( j = 0; j < iLength; ) 1045 | { 1046 | mLength = CH341_PACKET_LENGTH - 1; 1047 | if( mLength > iLength - j ) 1048 | mLength = iLength - j; 1049 | mWrBuf[i++] = CH341A_CMD_SPI_STREAM; 1050 | if( StreamMode & 0x80 ) 1051 | { 1052 | while( mLength-- ) 1053 | { 1054 | c1 = mMsbTable[*((PUCHAR)ioBuffer + (j >> 1))]; 1055 | c2 = mMsbTable[*((PUCHAR)ioBuffer2 + (j >> 1))]; 1056 | mWrBuf[i++] = (UCHAR)((j & 0x01)?(c1 & 0xF0 | c2 >> 4 & 0x0F ):(c1 << 4 & 0xF0 | c2 & 0x0F)); 1057 | j++; 1058 | } 1059 | } 1060 | else 1061 | { 1062 | while( mLength-- ) 1063 | { 1064 | c1 = *((PUCHAR)ioBuffer + (j >> 1)); 1065 | c2 = *((PUCHAR)ioBuffer + (j >> 1)); 1066 | mWrBuf[i++] = (UCHAR)((j & 0x01)?(c1 & 0xF0 | c2 >> 4 & 0x0F ):(c1 << 4 & 0xF0 | c2 & 0x0F)); 1067 | j++; 1068 | } 1069 | } 1070 | if( VenIC == 0x20 && i % CH341_PACKET_LENGTH == 0 ) 1071 | { 1072 | mWrBuf[i] = mWrBuf[i+1] = 0; 1073 | i += CH341_PACKET_LENGTH; 1074 | } 1075 | } 1076 | } 1077 | } 1078 | 1079 | mLength = 0; 1080 | mWrBuf[i] = CH341_PACKET_LENGTH - 1; 1081 | mWrBuf[i+4] = (iLength + CH341_PACKET_LENGTH -1 - 1)/(CH341_PACKET_LENGTH - 1); 1082 | i = i + 8; 1083 | j = CH34xWriteRead( i, mWrBuf, &mLength,((ULONG)ioBuffer2 < 4?ioBuffer:mWrBuf)); 1084 | // if( j && mLength != iLength ) 1085 | // j = false; 1086 | 1087 | // high bit mode transform normal display mode 1088 | if( iChipselect & 0x80 ) 1089 | { 1090 | mBuffer[0] = CH341A_CMD_UIO_STREAM; 1091 | mBuffer[1] = (UCHAR)(CH341A_CMD_UIO_STM_OUT | 0x37); 1092 | mBuffer[2] = CH341A_CMD_UIO_STM_END; 1093 | mLength = 3; 1094 | if( CH34xWriteData( mBuffer, &mLength )) 1095 | { 1096 | if( mLength < 2 ) 1097 | { 1098 | printf("Error in SPI......"); 1099 | return false; 1100 | } 1101 | } 1102 | else 1103 | return false; 1104 | } 1105 | if( j ) 1106 | { 1107 | if((ULONG)ioBuffer2 < 4 ) 1108 | { 1109 | if( StreamMode & 0x80 ) 1110 | { 1111 | for( i = 0; i < iLength; i++ ) 1112 | *((PUCHAR)ioBuffer + i) = mMsbTable[*((PUCHAR)ioBuffer + i)]; 1113 | } 1114 | } 1115 | else 1116 | { 1117 | for( i = 0; i < iLength; i += 2 ) 1118 | { 1119 | c1 = mWrBuf[i]; 1120 | c2 = mWrBuf[i+1]; 1121 | if( StreamMode & 0x80 ) 1122 | { 1123 | *((PUCHAR)ioBuffer + (i >> 1)) = mMsbTable[c1 >> 4 & 0xF0 | c2 & 0xF0]; 1124 | *((PUCHAR)ioBuffer2 + (i >> 1)) = mMsbTable[c1 & 0x0F | c2 << 4 & 0xF0]; 1125 | } 1126 | else 1127 | { 1128 | *((PUCHAR)ioBuffer + (i >> 1)) = (UCHAR)(c1 >> 4 & 0x0F | c2 & 0xF0 ); 1129 | *((PUCHAR)ioBuffer + (i >> 1)) = (UCHAR)(c1 & 0x0F | c2 << 4 & 0xF0); 1130 | } 1131 | } 1132 | } 1133 | } 1134 | if( mReturn > DEFAULT_BUFFER_LEN ) 1135 | free( mWrBuf ); 1136 | return ( j ); 1137 | } 1138 | 1139 | /* 1140 | * ******************************************************************** 1141 | * FUNCTION : Write/Read Flash Data (For one in one out SPI) 1142 | * arg: 1143 | * iChipselect : Flash cs enable 1144 | * iLength : the length of data 1145 | * ioBuffer : one in one out buffer 1146 | * ******************************************************************** 1147 | */ 1148 | // Note : StreamMode must set first 1149 | BOOL CH34xStreamSPI4( ULONG iChipSelect, ULONG iLength, PVOID ioBuffer ) 1150 | { 1151 | int retval = 0; 1152 | if( VenIC >= 0x25 && VenIC < 0x30 ) 1153 | return false; 1154 | StreamMode = 0x81; 1155 | if( StreamMode & 0x04 ) 1156 | { 1157 | if( CH34xSetStream( StreamMode & 0xFB ) == false ) 1158 | return false; 1159 | } 1160 | retval = CH34xStreamSPIx( iChipSelect, iLength, ioBuffer, (PVOID)1 ); 1161 | 1162 | return retval; 1163 | } 1164 | 1165 | 1166 | -------------------------------------------------------------------------------- /CH341PAR_LINUX/lib/ch34x_lib.c: -------------------------------------------------------------------------------- 1 | // Created on: Nov 28, 2013 2 | /* 3 | * File : ch34x_lib.c ch34x_lib.h 4 | * 5 | ********************************************************************** 6 | *********** Copyright (C) WCH 2013.11.28 *************** 7 | *********** web: http://www.wch.cn *************** 8 | *********** AUTHOR: TECH33 (tech@wch.cn) *************** 9 | *********** Used for USB Interface Chip (CH341) *************** 10 | *********** Nanjing QinHeng Electronics Co.,Ltd *************** 11 | ********************************************************************** 12 | * 13 | * Running Environment: Linux 14 | * This file is used for CH34x in Epp/MEM/I2C/SPI 15 | * 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include //for 'ioctl' 23 | #include 24 | #include 25 | #include 26 | 27 | #include "ch34x_lib.h" 28 | 29 | #define CH34x_GET_DRV_VERSION 0x00000001 30 | #define CH34x_CHIP_VERSION 0x00000003 31 | #define CH34x_FUNCTION_SETPARA_MODE 0x00000004 32 | #define CH34x_FUNCTION_READ_MODE 0x00000005 33 | #define CH34x_FUNCTION_WRITE_MODE 0x00000006 34 | #define CH34x_I2C_READ_MODE 0x00000007 35 | #define CH34x_I2C_WRITE_MODE 0x00000008 36 | #define CH34x_PIPE_DATA_DOWN 0x00000009 37 | #define CH34x_PIPE_WRITE_READ 0x0000000a 38 | #define CH34x_PIPE_DEVICE_CTRL 0x0000000b 39 | 40 | 41 | int dev_fd; 42 | unsigned char VenIC; 43 | unsigned char StreamMode = 1; 44 | 45 | /* 46 | * ******************************************************************** 47 | * FUNCTION : Open Device 48 | * arg: 49 | * index : the number of device 50 | * ******************************************************************** 51 | */ 52 | int CH34xOpenDevice( UCHAR index ) 53 | { 54 | int retval = 0; 55 | char dev_path[20] = {'\0'}; 56 | memset( dev_path, 0, sizeof(dev_path)); 57 | sprintf( dev_path, "%s%c", "/dev/ch34x_pis", '0' + index); 58 | 59 | dev_fd = open( dev_path, O_RDWR ); 60 | if( dev_fd == -1 ) 61 | { 62 | printf("open /dev/ch34x_pis error, LINE : %d\n",__LINE__ ); 63 | return false; 64 | } 65 | // printf("Open successful\n"); 66 | 67 | return dev_fd; 68 | } 69 | 70 | /* 71 | * ******************************************************************** 72 | * FUNCTION : Close Device 73 | * ******************************************************************** 74 | */ 75 | void CH34xCloseDevice() 76 | { 77 | close( dev_fd ); 78 | } 79 | 80 | /* 81 | * ******************************************************************** 82 | * FUNCTION : Get Driver Version 83 | * arg: 84 | * drv_version : output buffer of driver version 85 | * ******************************************************************** 86 | */ 87 | BOOL CH34x_GetDrvVer( char *drv_version ) 88 | { 89 | int retval = 0; 90 | 91 | retval = ioctl( dev_fd, CH34x_GET_DRV_VERSION, (unsigned long)drv_version ); 92 | if( retval == -1 ) 93 | { 94 | printf( "CH34x_GET_DRV_VERSION function error line:%d\n", __LINE__ ); 95 | return false; 96 | } 97 | 98 | return true; 99 | } 100 | 101 | /* 102 | * ******************************************************************** 103 | * FUNCTION : Get Chip ID 104 | * arg: 105 | * VendorId : output data of chip version(CH341A : 0x0030) 106 | * ******************************************************************** 107 | */ 108 | BOOL CH34x_GetVendorId( PULONG VendorId ) 109 | { 110 | int retval = 0; 111 | retval = ioctl( dev_fd, CH34x_CHIP_VERSION, (unsigned long)VendorId); 112 | if( retval == -1 ) 113 | { 114 | printf("Get Chip Version Error,line:%d\n",__LINE__); 115 | return false; 116 | } 117 | 118 | VenIC = (UCHAR)*VendorId; 119 | // printf("VenIc is 0x%x\n",VenIC); 120 | return true; 121 | } 122 | 123 | //Mode = 0 ------>EPP Mode 124 | //Mode = 1 ------>EPP Mode 125 | //Mode = 2 ------>MEM Mode 126 | /* 127 | * ******************************************************************** 128 | * FUNCTION : Set Para Mode 129 | * arg: 130 | * Mode : set Para Mode( EPP or MEM ) 131 | * ******************************************************************** 132 | */ 133 | BOOL CH34xSetParaMode( ULONG Mode ) 134 | { 135 | int retval = 0; 136 | 137 | retval = ioctl( dev_fd, CH34x_FUNCTION_SETPARA_MODE, Mode); 138 | if( retval < 0 ) 139 | { 140 | printf("SetPara Error\n"); 141 | return false; 142 | } 143 | 144 | return true; 145 | } 146 | 147 | //Mode = 0 ------>EPP Mode 148 | //Mode = 1 ------>EPP Mode 149 | //Mode = 2 ------>MEM Mode 150 | /* 151 | * ******************************************************************** 152 | * FUNCTION : Init Para 153 | * arg: 154 | * Mode : first reset ,then set Para Mode( EPP or MEM ) 155 | * ******************************************************************** 156 | */ 157 | BOOL CH34xInitParallel( ULONG Mode ) 158 | { 159 | int retval = 0; 160 | 161 | retval = ioctl( dev_fd, CH34x_PIPE_DEVICE_CTRL, Mode); 162 | if( retval < 0 ) 163 | { 164 | printf("Init Parallel Error,LINE : %d\n", __LINE__); 165 | return false; 166 | } 167 | return true; 168 | } 169 | 170 | //PipeMode = 1 ------>Read from Pipe1 171 | //PipeMode = 0 ------>Read from Pipe0 172 | /* 173 | * ******************************************************************** 174 | * FUNCTION : EPP READ 175 | * arg: 176 | * oBuffer : Output buffer 177 | * ioLength: should read the length of Data/Addr 178 | * PipeMode: Read Pipe 179 | * -->0 Read Pipe0 Data 180 | * -->1 Read Pipe1 Addr 181 | * ******************************************************************** 182 | */ 183 | int CH34xEppRead( PUCHAR oBuffer, ULONG ioLength, ULONG PipeMode ) 184 | { 185 | int retval = 0; 186 | ULONG mReturnlen; 187 | retval = ioctl( dev_fd, CH34x_FUNCTION_READ_MODE, PipeMode ); 188 | if( retval < 0 ) 189 | { 190 | printf("Set Pipe Error\n"); 191 | return false; 192 | } 193 | mReturnlen = read( dev_fd, oBuffer, ioLength ); 194 | if( mReturnlen != ioLength ) 195 | { 196 | printf("Numbers of wanted output is not equal to input\n"); 197 | return false; 198 | } 199 | 200 | return mReturnlen; 201 | } 202 | 203 | //PipeMode = 1 ------>Read from Pipe1 204 | //PipeMode = 0 ------>Read from Pipe0 205 | /* 206 | * ******************************************************************** 207 | * FUNCTION : EPP Write 208 | * arg: 209 | * iBuffer : Iutput buffer 210 | * ioLength: should Write the length of Data/Addr 211 | * PipeMode: Write Pipe 212 | * -->0 Read Pipe0 Data 213 | * -->1 Read Pipe1 Addr 214 | * ******************************************************************** 215 | */ 216 | int CH34xEppWrite( PUCHAR iBuffer, ULONG ioLength, ULONG PipeMode ) 217 | { 218 | int retval =0; 219 | retval = ioctl( dev_fd, CH34x_FUNCTION_WRITE_MODE, PipeMode ); 220 | if( retval < 0 ) 221 | { 222 | printf("Set Write Pipe Error\n"); 223 | return false; 224 | } 225 | retval = write( dev_fd, iBuffer, ioLength ); 226 | if( retval < 0 ) 227 | { 228 | printf("Write Epp Error\n"); 229 | return false; 230 | } 231 | 232 | return true; 233 | } 234 | 235 | /* 236 | * ******************************************************************** 237 | * FUNCTION : EPP Write Data 238 | * arg: 239 | * iBuffer : Output buffer 240 | * ioLength: should Write the length of Data 241 | * ******************************************************************** 242 | */ 243 | int CH34xEppWriteData( PUCHAR iBuffer, ULONG ioLength ) 244 | { 245 | int retval; 246 | retval = CH34xEppWrite( iBuffer, ioLength, 0); 247 | if( !retval ) 248 | return false; 249 | return true; 250 | } 251 | 252 | /* 253 | * ******************************************************************** 254 | * FUNCTION : EPP Read Data 255 | * arg: 256 | * oBuffer : Iutput buffer 257 | * ioLength: should read the length of Data 258 | * ******************************************************************** 259 | */ 260 | int CH34xEppReadData( PUCHAR oBuffer, ULONG ioLength ) 261 | { 262 | int retval; 263 | retval = CH34xEppRead( oBuffer, ioLength, 0 ); // set Pipe0,then Read Data from pipe0 264 | if( !retval ) 265 | return false; 266 | return retval; 267 | } 268 | 269 | /* 270 | * ******************************************************************** 271 | * FUNCTION : EPP Write Addr 272 | * arg: 273 | * iBuffer : Output buffer Data 274 | * ioLength: should write the length of Addr 275 | * ******************************************************************** 276 | */ 277 | int CH34xEppWriteAddr( PUCHAR iBuffer, ULONG ioLength ) 278 | { 279 | int retval; 280 | retval = CH34xEppWrite( iBuffer, ioLength, 1 ); // set Pipe1,then Write Data from pipe1 281 | if( !retval ) 282 | return false; 283 | return true; 284 | } 285 | 286 | /* 287 | * ******************************************************************** 288 | * FUNCTION : EPP Read Addr 289 | * arg: 290 | * oBuffer : Iutput buffer Data 291 | * ioLength: should read the length of Addr 292 | * ******************************************************************** 293 | */ 294 | int CH34xEppReadAddr( PUCHAR oBuffer, ULONG ioLength ) 295 | { 296 | int retval; 297 | retval = CH34xEppRead( oBuffer, ioLength, 1 ); // set Pipe1,then Read Data from pipe1 298 | if( !retval ) 299 | return false; 300 | return retval; 301 | } 302 | 303 | /* 304 | * ******************************************************************** 305 | * FUNCTION : EPP Set Addr 306 | * arg: 307 | * iAddr: Need set the iAddr 308 | * ******************************************************************** 309 | */ 310 | int CH34xEppSetAddr( ULONG iAddr ) 311 | { 312 | int retval; 313 | UCHAR iBuffer[4]; 314 | ULONG mLength; 315 | iBuffer[0] = iAddr; 316 | mLength = 1; 317 | retval = CH34xEppWriteAddr( iBuffer, mLength ); 318 | if( !retval ) 319 | return false; 320 | 321 | return true; 322 | } 323 | 324 | /* 325 | * ******************************************************************** 326 | * FUNCTION : Init MEM 327 | * ******************************************************************** 328 | */ 329 | BOOL CH34xInitMEM(void) 330 | { 331 | int retval = 0; 332 | ULONG iMode; 333 | iMode = 0x02; 334 | retval = CH34xInitParallel( iMode ); 335 | if( retval == false ) 336 | { 337 | printf("Init MEM Mode Error\n"); 338 | return false; 339 | } 340 | return true; 341 | } 342 | 343 | //PipeMode = 1 ------>Read from Pipe1 344 | //PipeMode = 0 ------>Read from Pipe0 345 | /* 346 | * ******************************************************************** 347 | * FUNCTION : MEM Read 348 | * arg: 349 | * oBuffer : Output buffer 350 | * ioLength: should Read the length of Data 351 | * PipeMode: Write Pipe 352 | * -->0 Read Pipe0 Data 353 | * -->1 Read Pipe1 Data 354 | * ******************************************************************** 355 | */ 356 | int CH34xMEMReadData( PUCHAR oBuffer, ULONG ioLength, ULONG PipeMode ) 357 | { 358 | int retval = 0; 359 | ULONG mReturnlen; 360 | retval = ioctl( dev_fd, CH34x_FUNCTION_READ_MODE, PipeMode ); 361 | if( retval < 0 ) 362 | { 363 | printf("Set Pipe Error\n"); 364 | return false; 365 | } 366 | mReturnlen = read( dev_fd, oBuffer, ioLength ); 367 | if( mReturnlen != ioLength ) 368 | { 369 | printf("Numbers of wanted output is not equal to input\n"); 370 | return false; 371 | } 372 | 373 | return mReturnlen; 374 | } 375 | 376 | //PipeMode = 1 ------>Read from Pipe1 377 | //PipeMode = 0 ------>Read from Pipe0 378 | /* 379 | * ******************************************************************** 380 | * FUNCTION : MEM Write 381 | * arg: 382 | * iBuffer : Iutput buffer 383 | * ioLength: should Write the length of Data 384 | * PipeMode: Write Pipe 385 | * -->0 Read Pipe0 Data 386 | * -->1 Read Pipe1 Data 387 | * ******************************************************************** 388 | */ 389 | int CH34xMEMWriteData( PUCHAR iBuffer, ULONG ioLength, ULONG PipeMode ) 390 | { 391 | int retval =0; 392 | retval = ioctl( dev_fd, CH34x_FUNCTION_WRITE_MODE, PipeMode ); 393 | if( retval < 0 ) 394 | { 395 | printf("Set Write Pipe Error\n"); 396 | return false; 397 | } 398 | retval = write( dev_fd, iBuffer, ioLength ); 399 | if( retval < 0 ) 400 | { 401 | printf("Write Epp Error\n"); 402 | return false; 403 | } 404 | 405 | return true; 406 | } 407 | 408 | /* 409 | * ******************************************************************** 410 | * FUNCTION : Set Stream Mode 411 | * arg: 412 | * Mode : Set Stream Mode 413 | * -> bit0~1 : set I2C SCL rate 414 | * --> 00 : Low Rate /20KHz 415 | * --> 01 : Default Rate /100KHz 416 | * --> 10 : Fast Rate /400KHz 417 | * --> 11 : Full Rate /750KHz 418 | * -> bit2 : set spi mode 419 | * --> 0 : one in one out(D3 :clk/ D5 :out/ D7 :in) 420 | * --> 1 : two in two out(D3 :clk/ D4,D5 :out/ D6,D7 :in) 421 | * -> bit7 : set spi data mode 422 | * --> 0 : low bit first 423 | * --> 1 : high bit first 424 | * other bits must keep 0 425 | * ******************************************************************** 426 | */ 427 | BOOL CH34xSetStream( ULONG Mode ) 428 | { 429 | UCHAR mBuffer[CH341_PACKET_LENGTH]; 430 | ULONG mLength; 431 | if( VenIC < 0x20 ) 432 | return false; 433 | StreamMode = (UCHAR)( Mode & 0x8F ); 434 | mBuffer[0] = CH341A_CMD_I2C_STREAM; 435 | mBuffer[1] = CH341A_CMD_I2C_STM_SET; 436 | mBuffer[2] = CH341A_CMD_I2C_STM_END; 437 | mLength = 3; 438 | if( CH34xWriteData( mBuffer, &mLength )) 439 | { 440 | if( mLength >= 2 ) 441 | return true; 442 | } 443 | return false; 444 | } 445 | 446 | /* 447 | * ******************************************************************** 448 | * FUNCTION : Set Delay 449 | * arg: 450 | * iDelay : set delay time(ms) 451 | * ******************************************************************** 452 | */ 453 | BOOL CH34xSetDelaymS( ULONG iDelay ) 454 | { 455 | UCHAR mBuffer[CH341_PACKET_LENGTH]; 456 | ULONG mLength; 457 | if( VenIC < 0x20 ) 458 | return false; 459 | while( iDelay ) 460 | { 461 | mLength = iDelay >= CH341A_CMD_I2C_STM_DLY ? CH341A_CMD_I2C_STM_DLY : iDelay; 462 | iDelay -= mLength; 463 | mBuffer[0] = CH341A_CMD_I2C_STREAM; 464 | mBuffer[1] = (UCHAR)( CH341A_CMD_I2C_STM_MS | mLength ); 465 | mBuffer[2] = CH341A_CMD_I2C_STM_END; 466 | mLength = 3; 467 | if(( CH34xWriteData( mBuffer, &mLength )) == false ) 468 | return false; 469 | } 470 | return true; 471 | } 472 | 473 | //This is needless for the moment 474 | BOOL CH34xReadData( PVOID oBuffer, PULONG ioLength ) 475 | { 476 | UCHAR mBuffer[MAX_BUFFER_LENGTH]; 477 | ULONG mLength; 478 | } 479 | 480 | /* 481 | * ******************************************************************** 482 | * FUNCTION : Write Data ( for i2c/flash ) 483 | * arg: 484 | * iBuffer : should Input data buffer 485 | * ioLength : write length of data 486 | * ******************************************************************** 487 | */ 488 | BOOL CH34xWriteData( PVOID iBuffer, PULONG ioLength ) 489 | { 490 | int retval = 0; 491 | int i=0; 492 | unsigned long mLen; 493 | struct{ 494 | ULONG length; 495 | PUCHAR ByteBuffer; 496 | }Write; 497 | if( *ioLength > MAX_BUFFER_LENGTH ) 498 | *ioLength = MAX_BUFFER_LENGTH; 499 | mLen = *ioLength; 500 | Write.length = ioLength; 501 | Write.ByteBuffer = (PUCHAR)malloc( sizeof( unsigned char ) * mLen ); 502 | memcpy( Write.ByteBuffer, (PUCHAR)iBuffer, mLen ); 503 | printf("ByteBuffer:"); 504 | for(i=0;i:%p\n",Read.iBuf); 555 | Read.oReadlen = iWriteLength; 556 | retval = ioctl( dev_fd, CH34x_PIPE_WRITE_READ, (unsigned long)&Read ); 557 | if( retval == -1 ) 558 | { 559 | printf("Error in pipe write/read\n"); 560 | return false; 561 | } 562 | return true; 563 | } 564 | 565 | 566 | /* 567 | * ******************************************************************** 568 | * FUNCTION : Set direction and output data of CH341 569 | * arg: 570 | * Data : Control direction and data 571 | 572 | * iEnbale : set direction and data enable 573 | * --> Bit16 High : effect on Bit15~8 of iSetDataOut 574 | * --> Bit17 High : effect on Bit15~8 of iSetDirOut 575 | * --> Bit18 High : effect on Bit7~0 of iSetDataOut 576 | * --> Bit19 High : effect on Bit7~0 of iSetDirOut 577 | * --> Bit20 High : effect on Bit23~16 of iSetDataOut 578 | * iSetDirOut : set io direction 579 | * -- > Bit High : Output 580 | * -- > Bit Low : Input 581 | * iSetDataOut : set io data 582 | * Output: 583 | * -- > Bit High : High level 584 | * -- > Bit Low : Low level 585 | * Note: 586 | * Bit7~Bit0<==>D7-D0 587 | * Bit8<==>ERR# Bit9<==>PEMP Bit10<==>INT# Bit11<==>SLCT Bit13<==>WAIT# Bit14<==>DATAS#/READ# Bit15<==>ADDRS#/ADDR/ALE 588 | * The pins below can only be used in output mode: 589 | * Bit16<==>RESET# Bit17<==>WRITE# Bit18<==>SCL Bit29<==>SDA 590 | * ******************************************************************** 591 | */ 592 | 593 | BOOL CH34xSetOutput( ULONG iEnable, ULONG iSetDirOut, ULONG iSetDataOut) 594 | { 595 | ULONG mLength; 596 | UCHAR mBuffer[32]; 597 | mBuffer[0] = CH341A_CMD_SET_OUTPUT; 598 | mBuffer[1] = 0x6A; 599 | mBuffer[2] = (UCHAR)( iEnable & 0x1F ); 600 | mBuffer[3] = (UCHAR)( iSetDataOut >> 8 & 0xEF ); 601 | mBuffer[4] = (UCHAR)( iSetDirOut >> 8 & 0xEF | 0x10 ); 602 | mBuffer[5] = (UCHAR)( iSetDataOut & 0xFF ); 603 | mBuffer[6] = (UCHAR)( iSetDirOut & 0xFF ); 604 | mBuffer[7] = (UCHAR)( iSetDataOut >> 16 & 0x0F ); 605 | mBuffer[8] = 0; 606 | mBuffer[9] = 0; 607 | mBuffer[10] = 0; 608 | mLength = 11; 609 | if ( CH34xWriteData( mBuffer, &mLength ) ) { //Write Data 610 | if ( mLength >= 8 ) return( true); 611 | } 612 | return( false); 613 | } 614 | 615 | 616 | /* 617 | * ******************************************************************** 618 | * FUNCTION : Set direction and output data of D5-D0 on CH341 619 | * arg: 620 | * Data : Control direction and data 621 | * iSetDirOut : set io direction 622 | * -- > Bit High : Output 623 | * -- > Bit Low : Input 624 | * iSetDataOut : set io data 625 | * Output: 626 | * -- > Bit High : High level 627 | * -- > Bit Low : Low level 628 | * ******************************************************************** 629 | */ 630 | 631 | BOOL CH34xSet_D5_D0( UCHAR iSetDirOut,UCHAR iSetDataOut) 632 | { 633 | ULONG mLength; 634 | UCHAR mBuffer[32]; 635 | mBuffer[0] = CH341A_CMD_UIO_STREAM; 636 | mBuffer[1] = (UCHAR)( CH341A_CMD_UIO_STM_OUT | iSetDataOut & 0x3F ); 637 | mBuffer[2] = (UCHAR)( CH341A_CMD_UIO_STM_DIR | iSetDirOut & 0x3F ); 638 | mBuffer[3] = CH341A_CMD_UIO_STM_END; 639 | mLength = 4; 640 | if ( CH34xWriteData( mBuffer, &mLength ) ) { //Write Data 641 | if ( mLength >= 3 ) return( true ); 642 | } 643 | return( false); 644 | } 645 | 646 | 647 | 648 | 649 | /* 650 | * ******************************************************************** 651 | * FUNCTION : Write/Read I2C Data Stream 652 | * This function issue a set of packets of iWriteBuffer data 653 | * arg: 654 | * iWriteLength : should write the length of data 655 | * iWriteBuffer : input buffer 656 | * oReadLength : should read the length of data 657 | * oReadBuffer : output buffer 658 | * ******************************************************************** 659 | */ 660 | BOOL CH34xStreamI2C( ULONG iWriteLength, PVOID iWriteBuffer, 661 | ULONG iReadLength, PVOID oReadBuffer ) 662 | { 663 | UCHAR mBuffer[MAX_BUFFER_LENGTH]; 664 | ULONG i, j, mLength; 665 | PUCHAR mWrBuf; 666 | 667 | if( VenIC < 0x20 ) 668 | return false; 669 | mLength = max( iWriteLength, iReadLength ); 670 | if( mLength > MAX_BUFFER_LENGTH ) 671 | return false; 672 | if( mLength <= DEFAULT_BUFFER_LEN ) 673 | mWrBuf = (PVOID)mBuffer; 674 | else 675 | { 676 | mWrBuf = (PVOID)malloc( sizeof( UCHAR ) * MAX_BUFFER_LENGTH ); 677 | if( mWrBuf == NULL) 678 | return false; 679 | } 680 | i = 0; 681 | mWrBuf[i++] = CH341A_CMD_I2C_STREAM; 682 | if(( StreamMode & 0x03 ) == 0 ) 683 | { 684 | mWrBuf[i++] = CH341A_CMD_I2C_STM_US | 10; 685 | mWrBuf[i++] = CH341A_CMD_I2C_STM_US | 10; 686 | } 687 | mWrBuf[i++] = CH341A_CMD_I2C_STM_STA; 688 | if( iWriteLength ) 689 | { 690 | for( j = 0; j < iWriteLength; j++) 691 | { 692 | mLength = CH341_PACKET_LENGTH - i % CH341_PACKET_LENGTH; 693 | if( mLength <= 2 ) 694 | { 695 | while( mLength-- ) 696 | mWrBuf[i++] = CH341A_CMD_I2C_STM_END; 697 | mLength = CH341_PACKET_LENGTH; 698 | } 699 | if( mLength >= CH341_PACKET_LENGTH ) 700 | { 701 | mWrBuf[i++] = CH341A_CMD_I2C_STREAM; 702 | mLength = CH341_PACKET_LENGTH - 1; 703 | 704 | } 705 | mLength--; 706 | mLength--; 707 | if( mLength > iWriteLength - j) 708 | mLength = iWriteLength - j; 709 | mWrBuf[i++] = (UCHAR)(CH341A_CMD_I2C_STM_OUT | mLength); 710 | while( mLength-- ) 711 | mWrBuf[i++] = *((PUCHAR)iWriteBuffer + j++ ); 712 | } 713 | 714 | } 715 | if( iReadLength ) 716 | { 717 | mLength = CH341_PACKET_LENGTH - i % CH341_PACKET_LENGTH; 718 | if( mLength <= 3 ) 719 | { 720 | while( mLength-- ) 721 | mWrBuf[i++] = CH341A_CMD_I2C_STM_END; 722 | mLength = CH341_PACKET_LENGTH; 723 | } 724 | if( mLength >= CH341_PACKET_LENGTH ) 725 | mWrBuf[i++] = CH341A_CMD_I2C_STREAM; 726 | if( iWriteLength > 1 ) 727 | { 728 | mWrBuf[i++] = CH341A_CMD_I2C_STM_STA; 729 | mWrBuf[i++] = (UCHAR)(CH341A_CMD_I2C_STM_OUT | 1); 730 | mWrBuf[i++] = *(PUCHAR)iWriteBuffer | 0x01; 731 | } 732 | else if( iWriteLength ) 733 | { 734 | i--; 735 | mWrBuf[i++] = *(PUCHAR)iWriteBuffer | 0x01; 736 | } 737 | for( j = 1; j < iReadLength; ) 738 | { 739 | mLength = CH341_PACKET_LENGTH - i % CH341_PACKET_LENGTH; 740 | if( mLength <= 1) 741 | { 742 | if( mLength ) 743 | mWrBuf[i++] = CH341A_CMD_I2C_STM_END; 744 | mLength = CH341_PACKET_LENGTH; 745 | } 746 | if( mLength >= CH341_PACKET_LENGTH ) 747 | mWrBuf[i++] = CH341A_CMD_I2C_STREAM; 748 | mLength = iReadLength - j >= CH341_PACKET_LENGTH ? CH341_PACKET_LENGTH : iReadLength - j; 749 | mWrBuf[i++] = (UCHAR)(CH341A_CMD_I2C_STM_IN | mLength); 750 | j += mLength; 751 | if( mLength >= CH341_PACKET_LENGTH ) 752 | { 753 | mWrBuf[i] = CH341A_CMD_I2C_STM_END; 754 | i += CH341_PACKET_LENGTH - i % CH341_PACKET_LENGTH; 755 | } 756 | } 757 | mLength = CH341_PACKET_LENGTH - i % CH341_PACKET_LENGTH; 758 | if( mLength <= 1 ) 759 | { 760 | if( mLength) 761 | mWrBuf[i++] = CH341A_CMD_I2C_STM_END; 762 | mLength = CH341_PACKET_LENGTH; 763 | } 764 | if( mLength >= CH341_PACKET_LENGTH ) 765 | mWrBuf[i++] = CH341A_CMD_I2C_STREAM; 766 | mWrBuf[i++] = CH341A_CMD_I2C_STM_IN; 767 | } 768 | mLength = CH341_PACKET_LENGTH - i % CH341_PACKET_LENGTH; 769 | if( mLength <= 1 ) 770 | { 771 | if( mLength ) 772 | mWrBuf[i++] = CH341A_CMD_I2C_STM_END; 773 | mLength = CH341_PACKET_LENGTH; 774 | } 775 | if( mLength >= CH341_PACKET_LENGTH ) 776 | mWrBuf[i++] = CH341A_CMD_I2C_STREAM; 777 | mWrBuf[i++] = CH341A_CMD_I2C_STM_STO; 778 | mWrBuf[i++] = CH341A_CMD_I2C_STM_END; 779 | mLength = 0; 780 | if( iReadLength ) 781 | { 782 | mWrBuf[i] = CH341_PACKET_LENGTH; 783 | mWrBuf[i+4] = (iReadLength + CH341_PACKET_LENGTH -1)/CH341_PACKET_LENGTH; 784 | i = i + 8; 785 | } 786 | if( iReadLength ) 787 | { 788 | j = CH34xWriteRead( i, mWrBuf, &mLength, oReadBuffer ); 789 | if( mLength != iReadLength ) 790 | { 791 | printf("Return length is not equal to input length\n"); 792 | j = false; 793 | } 794 | } 795 | else 796 | j = CH34xWriteData( mWrBuf, &i); 797 | 798 | // printf("Return mLength is %d\n", mLength); 799 | if( max( iWriteLength, iReadLength ) >= DEFAULT_BUFFER_LEN ) 800 | free( mWrBuf ); 801 | 802 | return ( j ); 803 | } 804 | 805 | /* 806 | * ******************************************************************** 807 | * FUNCTION : Read EEPROM Data (For I2C) 808 | * arg: 809 | * iEepromID : EEPROM TYPE 810 | * iAddr : the start addr for read 811 | * iLength : should read the length of data 812 | * oBuffer : output buffer 813 | * ******************************************************************** 814 | */ 815 | BOOL CH34xReadEEPROM( EEPROM_TYPE iEepromID, ULONG iAddr, 816 | ULONG iLength, PUCHAR oBuffer ) 817 | { 818 | ULONG mLen; 819 | UCHAR mWrBuf[4]; 820 | 821 | if( iEepromID >= ID_24C01 && iEepromID <= ID_24C16 ) 822 | { 823 | while( iLength ) 824 | { 825 | mWrBuf[0] = (UCHAR)( 0xA0 | (iAddr >> 7) & 0x0E ); 826 | mWrBuf[1] = (UCHAR)iAddr; 827 | mLen = min( iLength, DEFAULT_BUFFER_LEN ); 828 | if( !CH34xStreamI2C( 2, mWrBuf, mLen, oBuffer )) 829 | return false; 830 | iAddr += mLen; 831 | iLength -= mLen; 832 | oBuffer += mLen; 833 | } 834 | } 835 | else if( iEepromID >= ID_24C32 && iEepromID <= ID_24C4096 ) 836 | { 837 | 838 | while( iLength ) 839 | { 840 | mWrBuf[0] = (UCHAR)( 0xA0 | (iAddr >> 15 ) & 0x0E ); 841 | mWrBuf[1] = (UCHAR)( iAddr >> 8 ); 842 | mWrBuf[2] = (UCHAR)iAddr; 843 | mLen = min( iLength, DEFAULT_BUFFER_LEN ); 844 | if( !CH34xStreamI2C( 3, mWrBuf, mLen, oBuffer )) 845 | return false; 846 | iAddr += mLen; 847 | iLength -= mLen; 848 | oBuffer += mLen; 849 | } 850 | } 851 | else 852 | return false; 853 | 854 | return true; 855 | } 856 | 857 | /* 858 | * ******************************************************************** 859 | * FUNCTION : Write EEPROM Data (For I2C) 860 | * arg: 861 | * iEepromID : EEPROM TYPE 862 | * iAddr : the start addr for read 863 | * iLength : should write the length of data 864 | * iBuffer : Iutput buffer 865 | * ******************************************************************** 866 | */ 867 | 868 | //Note : Sometimes you should set Delay time( CH34xSetDelaymS()) after 869 | // CH34xStreamI2C() 870 | BOOL CH34xWriteEEPROM( EEPROM_TYPE iEepromID, ULONG iAddr, 871 | ULONG iLength, PUCHAR iBuffer ) 872 | { 873 | ULONG mLen; 874 | UCHAR mWrBuf[256]; 875 | if( iEepromID >= ID_24C01 && iEepromID <= ID_24C16 ) 876 | { 877 | while( iLength ) 878 | { 879 | mWrBuf[0] = (UCHAR)( 0xA0 | ( iAddr >>7 ) & 0x0E); 880 | mWrBuf[1] = (UCHAR)iAddr; 881 | mLen = iEepromID >= ID_24C04 ? 16 - ( iAddr & 15 ) : 8 - (iAddr & 7 ); 882 | if( mLen > iLength ) 883 | mLen = iLength; 884 | memcpy( &mWrBuf[2], iBuffer, mLen ); 885 | if( !CH34xStreamI2C( 2 + mLen, mWrBuf, 0, NULL )) 886 | return false; 887 | iAddr += mLen; 888 | iLength -= mLen; 889 | iBuffer += mLen; 890 | } 891 | } 892 | else if( iEepromID >= ID_24C32 && iEepromID <= ID_24C4096 ) 893 | { 894 | printf("Addr is %d\n",iAddr); 895 | printf("iLength is %d\n",iLength); 896 | printf("iBuffer is %x\n",*iBuffer); 897 | while( iLength ) 898 | { 899 | mWrBuf[0] = (UCHAR)( 0xA0 | ( iAddr >>15 ) & 0x0E ); 900 | mWrBuf[1] = (UCHAR)( iAddr >> 8 ); 901 | mWrBuf[2] = (UCHAR)iAddr; 902 | mLen = iEepromID >= ID_24C512 ? 128 - ( iAddr & 127) : (iEepromID >= ID_24C128 ? 64 - ( iAddr & 63 ) : 32 - ( iAddr & 31)); 903 | if( mLen > iLength ) 904 | mLen = iLength; 905 | memcpy( &mWrBuf[3], iBuffer, mLen ); 906 | printf("mWrBuf[3] is %x\n",mWrBuf[3]); 907 | if( !CH34xStreamI2C( 3 + mLen, mWrBuf, 0, NULL )) 908 | return false; 909 | iAddr += mLen; 910 | iLength -= mLen; 911 | iBuffer += mLen; 912 | 913 | } 914 | } 915 | else 916 | return false; 917 | 918 | return true; 919 | 920 | } 921 | 922 | //Used for high bit transform 923 | const UCHAR mMsbTable[256] = { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 924 | 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, // 0XH 925 | 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 926 | 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, // 1XH 927 | 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 928 | 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, // 2XH 929 | 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 930 | 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, // 3XH 931 | 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 932 | 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, // 4XH 933 | 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 934 | 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, // 5XH 935 | 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 936 | 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, // 6XH 937 | 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 938 | 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, // 7XH 939 | 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 940 | 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, // 8XH 941 | 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 942 | 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, // 9XH 943 | 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 944 | 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, // AXH 945 | 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 946 | 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, // BXH 947 | 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 948 | 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, // CXH 949 | 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 950 | 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, // DXH 951 | 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 952 | 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, // EXH 953 | 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 954 | 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF }; // FXH 955 | 956 | /* 957 | * ******************************************************************** 958 | * FUNCTION : Write/Read Flash Data (For SPI) 959 | * arg: 960 | * iChipselect : Flash cs enable 961 | * iLength : the length of data 962 | * ioBuffer : one in one out buffer 963 | * ioBuffer2 : two in two out buffer 964 | * ******************************************************************** 965 | */ 966 | BOOL CH34xStreamSPIx( ULONG iChipselect, ULONG iLength, 967 | PVOID ioBuffer, PVOID ioBuffer2 ) 968 | { 969 | UCHAR mBuffer[DEFAULT_BUFFER_LEN]; 970 | ULONG i, j, mLength, mSelect, mCount,mReturn; 971 | PUCHAR mWrBuf; 972 | UCHAR c1, c2; 973 | mReturn = iLength; 974 | if( VenIC < 0x20 ) 975 | { 976 | printf("Not support this device\n"); 977 | return false; 978 | } 979 | if( iLength <= DEFAULT_BUFFER_LEN/2 ) 980 | { 981 | mWrBuf = (PVOID)mBuffer; 982 | i = DEFAULT_BUFFER_LEN; 983 | } 984 | else 985 | { 986 | mWrBuf = (PVOID)malloc( sizeof( UCHAR ) * MAX_BUFFER_LENGTH ); 987 | if( mWrBuf == NULL ) 988 | return false; 989 | i = MAX_BUFFER_LENGTH; 990 | } 991 | memset( mWrBuf, 0, sizeof( UCHAR ) * i ); 992 | i = 0; 993 | if( iChipselect & 0x80 ) 994 | { 995 | mWrBuf[i++] = CH341A_CMD_UIO_STREAM; 996 | switch( iChipselect & 0x03 ) 997 | { 998 | case 0x00: //DCK/D3->0, D0 ->0 999 | mSelect = 0x36; 1000 | break; 1001 | case 0x01: //DCK/D3->0, D1 ->0 1002 | mSelect = 0x35; 1003 | break; 1004 | case 0x02: //DCK/D3->0, D2 ->0 1005 | mSelect = 0x33; 1006 | break; 1007 | default: //DCK/D3->0, D4 ->0 1008 | mSelect = 0x27; 1009 | break; 1010 | } 1011 | 1012 | mWrBuf[i++] = (UCHAR)( CH341A_CMD_UIO_STM_OUT | mSelect );// Output data 1013 | mWrBuf[i++] = (UCHAR)( CH341A_CMD_UIO_STM_DIR | 0x3F ); // set D5~D0 direct 1014 | mWrBuf[i++] = CH341A_CMD_UIO_STM_END; 1015 | i = CH341_PACKET_LENGTH; 1016 | } 1017 | if( iLength ) 1018 | { 1019 | if( (ULONG)ioBuffer2 < 4 ) 1020 | { 1021 | for( j = 0; j < iLength; ) 1022 | { 1023 | mLength = CH341_PACKET_LENGTH - 1; 1024 | if( mLength > iLength - j ) 1025 | mLength = iLength - j; 1026 | mWrBuf[i++] = CH341A_CMD_SPI_STREAM; 1027 | if( StreamMode & 0x80 ) 1028 | { 1029 | while( mLength-- ) 1030 | mWrBuf[i++] = mMsbTable[*((PUCHAR)ioBuffer + j++)]; 1031 | } 1032 | else 1033 | while( mLength-- ) 1034 | mWrBuf[i++] = *((PUCHAR)ioBuffer + j++); 1035 | if( VenIC == 0x20 && i % CH341_PACKET_LENGTH == 0 ) 1036 | { 1037 | mWrBuf[i] = mWrBuf[i+1] = 0; 1038 | i += CH341_PACKET_LENGTH; 1039 | } 1040 | } 1041 | } 1042 | else 1043 | { 1044 | for( j = 0; j < iLength; ) 1045 | { 1046 | mLength = CH341_PACKET_LENGTH - 1; 1047 | if( mLength > iLength - j ) 1048 | mLength = iLength - j; 1049 | mWrBuf[i++] = CH341A_CMD_SPI_STREAM; 1050 | if( StreamMode & 0x80 ) 1051 | { 1052 | while( mLength-- ) 1053 | { 1054 | c1 = mMsbTable[*((PUCHAR)ioBuffer + (j >> 1))]; 1055 | c2 = mMsbTable[*((PUCHAR)ioBuffer2 + (j >> 1))]; 1056 | mWrBuf[i++] = (UCHAR)((j & 0x01)?(c1 & 0xF0 | c2 >> 4 & 0x0F ):(c1 << 4 & 0xF0 | c2 & 0x0F)); 1057 | j++; 1058 | } 1059 | } 1060 | else 1061 | { 1062 | while( mLength-- ) 1063 | { 1064 | c1 = *((PUCHAR)ioBuffer + (j >> 1)); 1065 | c2 = *((PUCHAR)ioBuffer + (j >> 1)); 1066 | mWrBuf[i++] = (UCHAR)((j & 0x01)?(c1 & 0xF0 | c2 >> 4 & 0x0F ):(c1 << 4 & 0xF0 | c2 & 0x0F)); 1067 | j++; 1068 | } 1069 | } 1070 | if( VenIC == 0x20 && i % CH341_PACKET_LENGTH == 0 ) 1071 | { 1072 | mWrBuf[i] = mWrBuf[i+1] = 0; 1073 | i += CH341_PACKET_LENGTH; 1074 | } 1075 | } 1076 | } 1077 | } 1078 | 1079 | mLength = 0; 1080 | mWrBuf[i] = CH341_PACKET_LENGTH - 1; 1081 | mWrBuf[i+4] = (iLength + CH341_PACKET_LENGTH -1 - 1)/(CH341_PACKET_LENGTH - 1); 1082 | i = i + 8; 1083 | j = CH34xWriteRead( i, mWrBuf, &mLength,((ULONG)ioBuffer2 < 4?ioBuffer:mWrBuf)); 1084 | // if( j && mLength != iLength ) 1085 | // j = false; 1086 | 1087 | // high bit mode transform normal display mode 1088 | if( iChipselect & 0x80 ) 1089 | { 1090 | mBuffer[0] = CH341A_CMD_UIO_STREAM; 1091 | mBuffer[1] = (UCHAR)(CH341A_CMD_UIO_STM_OUT | 0x37); 1092 | mBuffer[2] = CH341A_CMD_UIO_STM_END; 1093 | mLength = 3; 1094 | if( CH34xWriteData( mBuffer, &mLength )) 1095 | { 1096 | if( mLength < 2 ) 1097 | { 1098 | printf("Error in SPI......"); 1099 | return false; 1100 | } 1101 | } 1102 | else 1103 | return false; 1104 | } 1105 | if( j ) 1106 | { 1107 | if((ULONG)ioBuffer2 < 4 ) 1108 | { 1109 | if( StreamMode & 0x80 ) 1110 | { 1111 | for( i = 0; i < iLength; i++ ) 1112 | *((PUCHAR)ioBuffer + i) = mMsbTable[*((PUCHAR)ioBuffer + i)]; 1113 | } 1114 | } 1115 | else 1116 | { 1117 | for( i = 0; i < iLength; i += 2 ) 1118 | { 1119 | c1 = mWrBuf[i]; 1120 | c2 = mWrBuf[i+1]; 1121 | if( StreamMode & 0x80 ) 1122 | { 1123 | *((PUCHAR)ioBuffer + (i >> 1)) = mMsbTable[c1 >> 4 & 0xF0 | c2 & 0xF0]; 1124 | *((PUCHAR)ioBuffer2 + (i >> 1)) = mMsbTable[c1 & 0x0F | c2 << 4 & 0xF0]; 1125 | } 1126 | else 1127 | { 1128 | *((PUCHAR)ioBuffer + (i >> 1)) = (UCHAR)(c1 >> 4 & 0x0F | c2 & 0xF0 ); 1129 | *((PUCHAR)ioBuffer + (i >> 1)) = (UCHAR)(c1 & 0x0F | c2 << 4 & 0xF0); 1130 | } 1131 | } 1132 | } 1133 | } 1134 | if( mReturn > DEFAULT_BUFFER_LEN ) 1135 | free( mWrBuf ); 1136 | return ( j ); 1137 | } 1138 | 1139 | /* 1140 | * ******************************************************************** 1141 | * FUNCTION : Write/Read Flash Data (For one in one out SPI) 1142 | * arg: 1143 | * iChipselect : Flash cs enable 1144 | * iLength : the length of data 1145 | * ioBuffer : one in one out buffer 1146 | * ******************************************************************** 1147 | */ 1148 | // Note : StreamMode must set first 1149 | BOOL CH34xStreamSPI4( ULONG iChipSelect, ULONG iLength, PVOID ioBuffer ) 1150 | { 1151 | int retval = 0; 1152 | if( VenIC >= 0x25 && VenIC < 0x30 ) 1153 | return false; 1154 | StreamMode = 0x81; 1155 | if( StreamMode & 0x04 ) 1156 | { 1157 | if( CH34xSetStream( StreamMode & 0xFB ) == false ) 1158 | return false; 1159 | } 1160 | retval = CH34xStreamSPIx( iChipSelect, iLength, ioBuffer, (PVOID)1 ); 1161 | 1162 | return retval; 1163 | } 1164 | 1165 | 1166 | -------------------------------------------------------------------------------- /CH341PAR_LINUX/demo/ch34x_demo_gui.c: -------------------------------------------------------------------------------- 1 | // Created on: Dec 2, 2013 2 | /* 3 | * File : ch34x_demo_gui.c 4 | * 5 | ********************************************************************** 6 | *********** Copyright (C) WCH 2013.12.2 *************** 7 | *********** web: http://www.wch.cn *************** 8 | *********** AUTHOR: TECH33 (tech@wch.cn) *************** 9 | *********** Used for USB Interface Chip (CH341) *************** 10 | *********** Nanjing QinHeng Electronics Co.,Ltd *************** 11 | ********************************************************************** 12 | * 13 | * Running Environment: Linux 14 | * This file is used for CH34x in Epp/MEM/I2C/SPI 15 | * 16 | */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "ch34x_lib.h" 33 | #include "flash.h" 34 | 35 | #define MAX_LENGTH 255 //Input Max Length 36 | 37 | // GtkWidget 38 | GtkWidget *window_main; 39 | GtkWidget *window_sub; 40 | GtkWidget *entryEpp1; 41 | GtkWidget *entry_data_Epp1; 42 | GtkWidget *entryEpp2; 43 | GtkWidget *entry_data_Epp2; 44 | GtkWidget *entryMem; 45 | GtkWidget *entry_data_Mem; 46 | GtkWidget *entry_addr_I2c1; 47 | GtkWidget *entry_len_I2c1; 48 | GtkWidget *entry_data_I2c1; 49 | GtkWidget *entry_addr_I2c2; 50 | GtkWidget *entry_len_I2c2; 51 | GtkWidget *entry_data_I2c2; 52 | GtkWidget *entry_addr_Flash1; 53 | GtkWidget *entry_len_Flash1; 54 | GtkWidget *entry_data_Flash1; 55 | GtkWidget *entry_addr_Flash2; 56 | GtkWidget *entry_len_Flash2; 57 | GtkWidget *entry_data_Flash2; 58 | GtkWidget *entry_enable_Output; 59 | GtkWidget *entry_dirdata_Output; 60 | GtkWidget *entry_condata_Output; 61 | GtkWidget *entry_dirdata_D5D0; 62 | GtkWidget *entry_condata_D5D0; 63 | 64 | 65 | extern unsigned long retual_mem_length = 0; 66 | 67 | static int DEV_NUM = 4; 68 | static char gtk_dev_list[100]; 69 | static char *gtk_dev_path = "/dev/ch34x_pis"; 70 | char bufferframe[5][20] = {"EPP MODE", 71 | "MEM MODE", 72 | "EEPROM MODE", 73 | "FLASH MODE", 74 | "GPIO MODE"}; 75 | char buffer[5][10] = {"EPP", "MEM", "EEPROM", "FLASH","GPIO"}; 76 | 77 | extern int dev_fd; 78 | EEPROM_TYPE Eeprom_ID; //EEPROM Type 79 | unsigned long MemMode; //Mem Pipe 80 | // CHar -> Hex, Used for reading length 81 | unsigned long char_to_hex(const char *str) 82 | { 83 | int strlength = strlen(str); 84 | int i = 0; 85 | unsigned long dst = 0; 86 | for( i = 0; i < strlength; i++ ) 87 | { 88 | if(*(str + i) >= '0' && *(str + i) <= '9') 89 | { 90 | if(0 != i ) 91 | dst = (dst << 4); 92 | dst += *(str + i) - '0'; 93 | } 94 | else if(*(str + i) >= 'a' && *(str + i) <= 'f') 95 | { 96 | if(0 != i ) 97 | dst = (dst << 4); 98 | dst += *(str + i) - 'a' + 10; 99 | } 100 | else if(*(str + i) >= 'A' && *(str + i) <= 'F') 101 | { 102 | if(0 != i ) 103 | dst = (dst << 4); 104 | dst += *(str + i) - 'A' + 10; 105 | } 106 | } 107 | return dst; 108 | } 109 | // Hex -> Char, Used for gtk_entry_set_text Display 110 | void hex_to_char(unsigned char *dst, unsigned int src) 111 | { 112 | UCHAR temp[10]; 113 | int i = 0,j = 0; 114 | memset(temp, 0, sizeof(UCHAR) *10); 115 | while(1) 116 | { 117 | if( 0 == src ) 118 | break; 119 | if((src & 0x0f) >= 0 && (src & 0x0f) <= 9) 120 | temp[i++] = (src & 0xf) + '0'; 121 | else 122 | temp[i++] = ((src & 0xf) - 10) + 'a'; 123 | src = src >> 4; 124 | } 125 | for(j = 0; j < i; j++) 126 | { 127 | *(dst + j) = *(temp + (i-1-j)); 128 | } 129 | return; 130 | } 131 | //String -> Char 132 | void string_to_char(const unsigned char *str, unsigned char *dst) 133 | { 134 | int strlength = strlen(str); 135 | unsigned char temp[MAX_LENGTH]; 136 | int i, j = 0; 137 | memset(temp, 0, sizeof(unsigned char) * MAX_LENGTH); 138 | for(i = 0; i < strlength; i++) 139 | { 140 | if(*(str + i) >= '0' && *(str + i) <= '9') 141 | { 142 | temp[i] = *(str + i) -'0'; 143 | } 144 | else if(*(str + i) >= 'a' && *(str + i) <= 'f') 145 | { 146 | temp[i] = *(str + i) -'a' + 10; 147 | } 148 | else if(*(str + i) >= 'A' && *(str + i) <= 'F') 149 | { 150 | temp[i] = *(str + i) -'A' + 10; 151 | } 152 | } 153 | for(i= 0; i < strlength; i++) 154 | { 155 | dst[j++] = temp[i] * 16 + temp[++i]; 156 | } 157 | return; 158 | } 159 | //Char -> String, Used for gtk_entry_set_text display 160 | void char_to_string(unsigned char *str, char *dst, unsigned long mLen) 161 | { 162 | int strlength = mLen; 163 | unsigned char temp[MAX_LENGTH * 3]; 164 | int i, j = 0; 165 | memset(temp, 0,MAX_LENGTH * 3); 166 | memset(dst, 0,MAX_LENGTH * 3); 167 | for( i = 0; i < strlength; i++ ) 168 | { 169 | temp[j++] = str[i] / 16; 170 | temp[j++] = str[i] % 16; 171 | temp[j++] = ' '; 172 | } 173 | strlength = j - 1; 174 | for( j = 0; j < strlength; j++ ) 175 | { 176 | if( temp[j] == 0x20 ) 177 | { 178 | dst[j] = temp[j]; 179 | continue; 180 | } 181 | if(temp[j] >= 0 && temp[j] <= 9) 182 | dst[j] = temp[j] + '0'; 183 | else 184 | dst[j] = temp[j] - 10 + 'a'; 185 | } 186 | return; 187 | } 188 | 189 | static int get_ch34x_dev_list() 190 | { 191 | char dev_path[20] = {'\0'}; 192 | int i; 193 | memset(gtk_dev_list, '\0', sizeof(gtk_dev_list)); 194 | /* driver enumeration */ 195 | for( i = 0; i < DEV_NUM; i++ ) 196 | { 197 | sprintf(dev_path, "%s%c", gtk_dev_path, '0'+i); 198 | dev_fd = open(dev_path, O_RDWR); 199 | if( dev_fd == -1 ) 200 | break; 201 | CH34xCloseDevice(); 202 | } 203 | sprintf(gtk_dev_list, "Current devices number : %d", i); 204 | return 0; 205 | } 206 | 207 | void gtk_destroy_sub_window(GtkButton *button, gpointer data) 208 | { 209 | gtk_widget_destroy(window_sub); 210 | CH34xCloseDevice(); 211 | } 212 | 213 | // Radio event,Used for EEPROM Type Selection 214 | void On_Eeprom_Radio_Mode(GtkWidget *radio, gint data) 215 | { 216 | switch((int)data) 217 | { 218 | case 1: 219 | Eeprom_ID = ID_24C01; 220 | break; 221 | case 2: 222 | Eeprom_ID = ID_24C02; 223 | break; 224 | case 3: 225 | Eeprom_ID = ID_24C04; 226 | break; 227 | case 4: 228 | Eeprom_ID = ID_24C08; 229 | break; 230 | case 5: 231 | Eeprom_ID = ID_24C16; 232 | break; 233 | case 6: 234 | Eeprom_ID = ID_24C32; 235 | break; 236 | case 7: 237 | Eeprom_ID = ID_24C64; 238 | break; 239 | case 8: 240 | Eeprom_ID = ID_24C128; 241 | break; 242 | case 9: 243 | Eeprom_ID = ID_24C256; 244 | break; 245 | case 10: 246 | Eeprom_ID = ID_24C512; 247 | break; 248 | case 11: 249 | Eeprom_ID = ID_24C1024; 250 | break; 251 | case 12: 252 | Eeprom_ID = ID_24C2048; 253 | break; 254 | case 13: 255 | Eeprom_ID = ID_24C4096; 256 | break; 257 | } 258 | } 259 | 260 | // Radio event,Used for MEM Pipe Selection 261 | void On_MemAddr_Radio_Mode(GtkWidget *radio, gint data) 262 | { 263 | switch((int)data) 264 | { 265 | case 1: 266 | MemMode = 0x00; 267 | // printf("PipeMode is %d\n",MemMode); 268 | break; 269 | case 2: 270 | MemMode = 0x01; 271 | // printf("PipeMode is %d\n",MemMode); 272 | break; 273 | } 274 | } 275 | 276 | 277 | //Epp Mode: Date Write 278 | // gtk_entry_get_text read input data from entry 279 | //gtk_entry_set_text write data to entry 280 | void CH34x_EppWrite(GtkWidget *Button, gpointer Data) 281 | { 282 | unsigned long iLength = 0; 283 | unsigned char oBuffer[MAX_LENGTH]; 284 | unsigned char temp[10]; 285 | unsigned long retual_length; 286 | const char *len; 287 | int retval; 288 | memset(temp, 0, sizeof(temp)); 289 | retval = CH34xSetParaMode( 0 ); 290 | if( retval == false ) 291 | return; 292 | len = gtk_entry_get_text(GTK_ENTRY(entryEpp1)); 293 | iLength = char_to_hex(len); 294 | len = gtk_entry_get_text(GTK_ENTRY((GtkWidget *)Data)); 295 | retual_mem_length = strlen((unsigned char *)len) % 2 == 0 ? strlen((unsigned char *)len) / 2 : (strlen((unsigned char *)len) / 2 + 1); 296 | hex_to_char(temp, retual_mem_length); 297 | gtk_entry_set_text(GTK_ENTRY(entryEpp1), temp); 298 | string_to_char(len, oBuffer); 299 | retval = CH34xEppWriteData( oBuffer, iLength ); 300 | if( retval == false ) 301 | { 302 | printf("------->Write Error\n"); 303 | } 304 | } 305 | 306 | 307 | //Epp Mode: Data Read 308 | void CH34x_EppRead(GtkWidget *Button, gpointer Data) 309 | { 310 | unsigned long iLength = 0; 311 | unsigned char iBuffer[MAX_LENGTH] = {'\0'}; 312 | const char *len; 313 | const char *ReadBuffer; 314 | int retval; 315 | memset( iBuffer, 0, sizeof(iBuffer)); 316 | ReadBuffer = (char*)malloc(sizeof(unsigned char) * DEFAULT_BUFFER_LEN); 317 | len = gtk_entry_get_text(GTK_ENTRY(entryEpp1)); 318 | iLength = char_to_hex(len); 319 | retval = CH34xEppReadData( iBuffer, iLength ); 320 | if( retval != iLength ) 321 | { 322 | printf("------>Read Error\n"); 323 | } 324 | char_to_string(iBuffer, ReadBuffer, iLength); 325 | gtk_entry_set_text(GTK_ENTRY((GtkWidget *)Data), ReadBuffer); 326 | free( ReadBuffer ); 327 | } 328 | 329 | //Epp Mode : Addr Write 330 | void CH34x_EppWrite_Addr(GtkWidget *Button, gpointer Data) 331 | { 332 | unsigned long iLength = 0; 333 | unsigned char oBuffer[MAX_LENGTH]; 334 | unsigned char temp[10]; 335 | unsigned long retual_length; 336 | const char *len; 337 | int retval; 338 | memset(temp, 0, sizeof(temp)); 339 | memset(oBuffer, 0, sizeof(oBuffer)); 340 | retval = CH34xSetParaMode( 0 ); 341 | if( retval == false ) 342 | return; 343 | len = gtk_entry_get_text(GTK_ENTRY(entryEpp2)); 344 | iLength = char_to_hex(len); 345 | len = gtk_entry_get_text(GTK_ENTRY((GtkWidget *)Data)); 346 | retual_mem_length = strlen((unsigned char *)len) % 2 == 0 ? strlen((unsigned char *)len) / 2 : (strlen((unsigned char *)len) / 2 + 1); 347 | hex_to_char(temp, retual_mem_length); 348 | gtk_entry_set_text(GTK_ENTRY(entryEpp2), temp); 349 | string_to_char(len, oBuffer); 350 | retval = CH34xEppWriteAddr( oBuffer, iLength ); 351 | if( retval == false ) 352 | { 353 | printf("------->Write Error\n"); 354 | } 355 | } 356 | 357 | //Epp Mode : Addr Read 358 | void CH34x_EppRead_Addr(GtkWidget *Button, gpointer Data) 359 | { 360 | unsigned long iLength = 0; 361 | unsigned char iBuffer[MAX_LENGTH] = {'\0'}; 362 | const char *len; 363 | const char *ReadBuffer; 364 | int retval; 365 | ReadBuffer = (char*)malloc(sizeof(unsigned char) * DEFAULT_BUFFER_LEN); 366 | len = gtk_entry_get_text(GTK_ENTRY(entryEpp2)); 367 | iLength = char_to_hex(len); 368 | retval = CH34xEppReadAddr( iBuffer, iLength ); 369 | if( retval != iLength ) 370 | { 371 | printf("------>Read Error\n"); 372 | } 373 | char_to_string(iBuffer, ReadBuffer, iLength); 374 | gtk_entry_set_text(GTK_ENTRY((GtkWidget *)Data), ReadBuffer); 375 | free( ReadBuffer ); 376 | } 377 | 378 | //MEM Mode: Write data 379 | void CH34x_MEMWrite(GtkWidget *Button, gpointer Data) 380 | { 381 | unsigned long iLength = 0; 382 | unsigned char oBuffer[MAX_LENGTH]; 383 | const char *len; 384 | unsigned char temp[10]; 385 | int retval; 386 | 387 | memset(oBuffer, 0,sizeof(oBuffer)); 388 | memset(temp, 0, sizeof(temp)); 389 | retval = CH34xInitMEM(); 390 | if( retval == false ) 391 | { 392 | printf("CH34xInitMEM Error\n"); 393 | } 394 | len = gtk_entry_get_text(GTK_ENTRY(entryMem)); 395 | iLength = char_to_hex(len); 396 | len = gtk_entry_get_text(GTK_ENTRY((GtkWidget *)Data)); 397 | retual_mem_length = strlen((unsigned char *)len) % 2 == 0 ? strlen((unsigned char *)len) / 2 : (strlen((unsigned char *)len) / 2 + 1); 398 | string_to_char(len, oBuffer); 399 | hex_to_char(temp, retual_mem_length); 400 | gtk_entry_set_text(GTK_ENTRY(entryMem), temp); 401 | retval = CH34xMEMWriteData( oBuffer, iLength, MemMode ); 402 | if( retval == false ) 403 | { 404 | printf("------->Write Error\n"); 405 | } 406 | } 407 | 408 | //MEM Mode: Read Data 409 | void CH34x_MEMRead(GtkWidget *Button, gpointer Data) 410 | { 411 | unsigned long iLength = 0; 412 | unsigned char iBuffer[MAX_LENGTH] = {'\0'}; 413 | const char *len; 414 | const char *ReadBuffer; 415 | int retval; 416 | ReadBuffer = (char*)malloc(sizeof(unsigned char) * DEFAULT_BUFFER_LEN); 417 | len = gtk_entry_get_text(GTK_ENTRY(entryMem)); 418 | iLength = char_to_hex(len); 419 | retval = CH34xMEMReadData( iBuffer, iLength, MemMode ); 420 | if( retval != iLength ) 421 | { 422 | printf("------>Read Error\n"); 423 | } 424 | char_to_string(iBuffer, ReadBuffer, iLength); 425 | gtk_entry_set_text(GTK_ENTRY((GtkWidget *)Data), ReadBuffer); 426 | free( ReadBuffer ); 427 | } 428 | 429 | //EPP Mode Page 430 | void notebook_add_page1(GtkWidget *notebook, GtkWidget *frame) 431 | { 432 | GtkWidget *label; 433 | GtkWidget *frame1; 434 | GtkWidget *frame2; 435 | GtkWidget *vbox; 436 | GtkWidget *table; 437 | GtkWidget *RdBtnD; 438 | GtkWidget *WrBtnD; 439 | GtkWidget *RdBtnA; 440 | GtkWidget *WrBtnA; 441 | vbox = gtk_vbox_new(FALSE, 0); 442 | gtk_container_add(GTK_CONTAINER(frame), vbox); 443 | 444 | frame1 = gtk_frame_new("EPP DATA READ/WRITE"); 445 | gtk_box_pack_start(GTK_BOX(vbox), frame1, FALSE, FALSE, 5); 446 | table = gtk_table_new(6, 6, TRUE); 447 | gtk_container_add(GTK_CONTAINER(frame1), table); 448 | label = gtk_label_new("EPP Mode Read: WR#=1, DS#=0, AS#=1, D0~D7=input\n" \ 449 | "EPP Mode Write: WR#=0, DS#=0, AS#=1, D0~D7=output"); 450 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 4, 0, 2); 451 | 452 | label = gtk_label_new("Length :"); 453 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 454 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); 455 | entryEpp1 = gtk_entry_new(); 456 | gtk_table_attach_defaults(GTK_TABLE(table), entryEpp1, 1, 2, 2, 3); 457 | 458 | label = gtk_label_new("(0 ~ 0xff)"); 459 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 460 | gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, 2, 3); 461 | 462 | label = gtk_label_new("Data :"); 463 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 464 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4); 465 | entry_data_Epp1 = gtk_entry_new(); 466 | gtk_table_attach_defaults(GTK_TABLE(table), entry_data_Epp1, 1, 6, 3, 4); 467 | 468 | RdBtnD = gtk_button_new_with_label(" Read "); 469 | gtk_table_attach_defaults(GTK_TABLE(table), RdBtnD, 3, 4, 6, 7); 470 | WrBtnD = gtk_button_new_with_label(" Write "); 471 | gtk_table_attach_defaults(GTK_TABLE(table), WrBtnD, 4, 5, 6, 7); 472 | 473 | g_signal_connect(G_OBJECT(RdBtnD), "clicked", 474 | G_CALLBACK(CH34x_EppRead), (gpointer)entry_data_Epp1); 475 | g_signal_connect(G_OBJECT(WrBtnD), "clicked", 476 | G_CALLBACK(CH34x_EppWrite), (gpointer)entry_data_Epp1); 477 | 478 | 479 | frame2 = gtk_frame_new("EPP Addr READ/WRITE"); 480 | gtk_box_pack_start(GTK_BOX(vbox), frame2, FALSE, FALSE, 5); 481 | table = gtk_table_new(6, 6, TRUE); 482 | gtk_container_add(GTK_CONTAINER(frame2), table); 483 | label = gtk_label_new("EPP Mode Read: WR#=1, DS#=0, AS#=0, D0~D7=input\n" \ 484 | "EPP Mode Write: WR#=0, DS#=0, AS#=0, D0~D7=output"); 485 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 4, 0, 2); 486 | label = gtk_label_new("Length :"); 487 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 488 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); 489 | entryEpp2 = gtk_entry_new(); 490 | gtk_table_attach_defaults(GTK_TABLE(table), entryEpp2, 1, 2, 2, 3); 491 | label = gtk_label_new("(0 ~ 0xff)"); 492 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 493 | gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, 2, 3); 494 | label = gtk_label_new("Data :"); 495 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 496 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4); 497 | entry_data_Epp2 = gtk_entry_new(); 498 | gtk_table_attach_defaults(GTK_TABLE(table), entry_data_Epp2, 1, 6, 3, 4); 499 | RdBtnA = gtk_button_new_with_label(" Read "); 500 | gtk_table_attach_defaults(GTK_TABLE(table), RdBtnA, 3, 4, 6, 7); 501 | WrBtnA = gtk_button_new_with_label(" Write "); 502 | gtk_table_attach_defaults(GTK_TABLE(table), WrBtnA, 4, 5, 6, 7); 503 | g_signal_connect(G_OBJECT(RdBtnA), "clicked", 504 | G_CALLBACK(CH34x_EppRead_Addr), (gpointer)entry_data_Epp2); 505 | g_signal_connect(G_OBJECT(WrBtnA), "clicked", 506 | G_CALLBACK(CH34x_EppWrite_Addr), (gpointer)entry_data_Epp2); 507 | 508 | label = gtk_label_new(buffer[0]); 509 | gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label); 510 | } 511 | 512 | //MEM Mode Page 513 | void notebook_add_page2(GtkWidget *notebook, GtkWidget *frame) 514 | { 515 | GtkWidget *label; 516 | GtkWidget *frame1; 517 | GtkWidget *frame2; 518 | GtkWidget *vbox; 519 | GtkWidget *hbox; 520 | GtkWidget *table; 521 | GtkWidget *RdBtn; 522 | GtkWidget *WrBtn; 523 | GtkWidget *radioBtn1; 524 | GtkWidget *radioBtn2; 525 | 526 | MemMode = 0x00; 527 | vbox = gtk_vbox_new(FALSE, 0); 528 | gtk_container_add(GTK_CONTAINER(frame), vbox); 529 | frame1 = gtk_frame_new("MEM ADDR MODE CONFIGURE"); 530 | gtk_box_pack_start(GTK_BOX(vbox), frame1, FALSE, FALSE, 20); 531 | hbox = gtk_hbox_new(FALSE, 20); 532 | gtk_container_add(GTK_CONTAINER(frame1), hbox); 533 | radioBtn1 = gtk_radio_button_new_with_label(NULL, "Read/Write MEM Addr0 Mode"); 534 | gtk_box_pack_start(GTK_BOX(hbox), radioBtn1, FALSE, FALSE, 20); 535 | radioBtn2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn1), "Read/Write MEM Addr1 Mode"); 536 | gtk_box_pack_start(GTK_BOX(hbox), radioBtn2, FALSE, FALSE, 20); 537 | g_signal_connect(G_OBJECT(radioBtn1), "released", 538 | G_CALLBACK(On_MemAddr_Radio_Mode), (gpointer)1); 539 | g_signal_connect(G_OBJECT(radioBtn2), "released", 540 | G_CALLBACK(On_MemAddr_Radio_Mode), (gpointer)2); 541 | frame2 = gtk_frame_new("MEM DATA READ/WRITE"); 542 | gtk_box_pack_start(GTK_BOX(vbox), frame2, FALSE, FALSE, 20); 543 | table = gtk_table_new(6, 6, TRUE); 544 | gtk_container_add(GTK_CONTAINER(frame2), table); 545 | label = gtk_label_new("MEM Mode Read: WR#=1, DS#/RD#=0, AS#=0, D0~D7=input\n" \ 546 | "MEM Mode Write: WR#=0, DS#/RD#=1, AS#=0, D0~D7=output"); 547 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 5, 0, 2); 548 | label = gtk_label_new("Length :"); 549 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 550 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); 551 | entryMem = gtk_entry_new(); 552 | gtk_table_attach_defaults(GTK_TABLE(table), entryMem, 1, 3, 2, 3); 553 | label = gtk_label_new("(0 ~ 0xff)"); 554 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 555 | gtk_table_attach_defaults(GTK_TABLE(table), label, 3, 4, 2, 3); 556 | label = gtk_label_new("Data :"); 557 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 558 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4); 559 | entry_data_Mem = gtk_entry_new(); 560 | gtk_table_attach_defaults(GTK_TABLE(table), entry_data_Mem, 1, 6, 3, 4); 561 | RdBtn = gtk_button_new_with_label(" Read "); 562 | gtk_table_attach_defaults(GTK_TABLE(table), RdBtn, 3, 4, 6, 7); 563 | WrBtn = gtk_button_new_with_label(" Write "); 564 | gtk_table_attach_defaults(GTK_TABLE(table), WrBtn, 4, 5, 6, 7); 565 | g_signal_connect(G_OBJECT(RdBtn), "clicked", 566 | G_CALLBACK(CH34x_MEMRead), (gpointer)entry_data_Mem); 567 | g_signal_connect(G_OBJECT(WrBtn), "clicked", 568 | G_CALLBACK(CH34x_MEMWrite), (gpointer)entry_data_Mem); 569 | 570 | label = gtk_label_new(buffer[1]); 571 | gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label); 572 | } 573 | 574 | //EEPROM Write 575 | void CH34x_EEPROM_Write(GtkWidget *Button, gpointer Data) 576 | { 577 | unsigned long iLength = 0; 578 | unsigned long iAddr; 579 | unsigned char oBuffer[MAX_LENGTH]; 580 | const char *len; 581 | unsigned int retual_length; 582 | unsigned char *Addr_tmp; 583 | unsigned char temp[10]; 584 | int retval; 585 | 586 | memset(oBuffer, 0, sizeof(oBuffer)); 587 | memset(temp, 0, sizeof(temp)); 588 | Addr_tmp = gtk_entry_get_text(GTK_ENTRY(entry_addr_I2c1)); 589 | iAddr = char_to_hex(Addr_tmp); 590 | len = gtk_entry_get_text(GTK_ENTRY(entry_len_I2c1)); 591 | iLength = char_to_hex(len); 592 | len = NULL; 593 | len = gtk_entry_get_text(GTK_ENTRY((GtkWidget *)Data)); 594 | retual_length = strlen((unsigned char *)len) % 2 == 0 ? strlen((unsigned char *)len) / 2 : (strlen((unsigned char *)len) / 2 + 1);; 595 | hex_to_char(temp, retual_length); 596 | gtk_entry_set_text(GTK_ENTRY(entry_len_I2c1), temp); 597 | string_to_char(len, oBuffer); 598 | retval = CH34xWriteEEPROM( Eeprom_ID, iAddr, retual_length, oBuffer ); 599 | if( retval == false ) 600 | { 601 | printf("------->Write Error\n"); 602 | } 603 | } 604 | 605 | //EEPROM Mode -> Read 606 | void CH34x_EEPROM_Read(GtkWidget *Button, gpointer Data) 607 | { 608 | unsigned long iLength = 0; 609 | unsigned long iAddr; 610 | unsigned char iBuffer[MAX_LENGTH] = {'\0'}; 611 | const char *len; 612 | unsigned char *Addr_tmp; 613 | const char *ReadBuffer; 614 | int retval; 615 | int i; 616 | ReadBuffer = (char*)malloc(sizeof(unsigned char) * DEFAULT_BUFFER_LEN); 617 | Addr_tmp = gtk_entry_get_text(GTK_ENTRY(entry_addr_I2c2)); 618 | iAddr = char_to_hex(Addr_tmp); 619 | len = gtk_entry_get_text(GTK_ENTRY(entry_len_I2c2)); 620 | iLength = char_to_hex(len); 621 | retval = CH34xReadEEPROM( Eeprom_ID, iAddr, iLength, iBuffer ); 622 | if( retval == false ) 623 | { 624 | printf("Read EEPROM Error\n"); 625 | } 626 | char_to_string( iBuffer, ReadBuffer, iLength ); 627 | gtk_entry_set_text(GTK_ENTRY((GtkWidget *)Data), ReadBuffer); 628 | free( ReadBuffer ); 629 | } 630 | 631 | //EEPROM Mode Page 632 | void notebook_add_page3(GtkWidget *notebook, GtkWidget *frame) 633 | { 634 | GtkWidget *label; 635 | GtkWidget *hbox; 636 | GtkWidget *vbox1; 637 | GtkWidget *vbox2; 638 | GtkWidget *WrBtn; 639 | GtkWidget *RdBtn; 640 | GtkWidget *frame1; 641 | GtkWidget *frame2; 642 | GtkWidget *frame3; 643 | GtkWidget *table; 644 | GtkWidget *radioBtn1; 645 | GtkWidget *radioBtn2; 646 | GtkWidget *radioBtn3; 647 | GtkWidget *radioBtn4; 648 | GtkWidget *radioBtn5; 649 | GtkWidget *radioBtn6; 650 | GtkWidget *radioBtn7; 651 | GtkWidget *radioBtn8; 652 | GtkWidget *radioBtn9; 653 | GtkWidget *radioBtn10; 654 | GtkWidget *radioBtn11; 655 | GtkWidget *radioBtn12; 656 | GtkWidget *radioBtn13; 657 | 658 | // GtkWidget *scroll_window; 659 | // GtkWidget *buffer1; 660 | 661 | Eeprom_ID = ID_24C08; 662 | hbox = gtk_hbox_new(FALSE, 0); 663 | gtk_container_add(GTK_CONTAINER(frame), hbox); 664 | frame1 = gtk_frame_new("EEPROM Type"); 665 | gtk_box_pack_start(GTK_BOX(hbox), frame1, FALSE, FALSE, 10); 666 | vbox1 = gtk_vbox_new(FALSE, 0); 667 | gtk_container_add(GTK_CONTAINER(frame1), vbox1); 668 | radioBtn1 = gtk_radio_button_new_with_label(NULL, "24C01"); 669 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn1, FALSE, FALSE, 5); 670 | g_signal_connect(G_OBJECT(radioBtn1),"released", 671 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)1); 672 | radioBtn2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn1), "24C02"); 673 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn2, FALSE, FALSE, 5); 674 | g_signal_connect(G_OBJECT(radioBtn2),"released", 675 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)2); 676 | radioBtn3 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn2), "24C04"); 677 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn3, FALSE, FALSE, 5); 678 | g_signal_connect(G_OBJECT(radioBtn3),"released", 679 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)3); 680 | radioBtn4 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn3), "24C08"); 681 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn4, FALSE, FALSE, 5); 682 | g_signal_connect(G_OBJECT(radioBtn4),"released", 683 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)4); 684 | radioBtn5 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn4), "24C16"); 685 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn5, FALSE, FALSE, 5); 686 | g_signal_connect(G_OBJECT(radioBtn5),"released", 687 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)5); 688 | radioBtn6 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn5), "24C32"); 689 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn6, FALSE, FALSE, 5); 690 | g_signal_connect(G_OBJECT(radioBtn6),"released", 691 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)6); 692 | radioBtn7 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn6), "24C64"); 693 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn7, FALSE, FALSE, 5); 694 | g_signal_connect(G_OBJECT(radioBtn7),"released", 695 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)7); 696 | radioBtn8 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn7), "24C128"); 697 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn8, FALSE, FALSE, 5); 698 | g_signal_connect(G_OBJECT(radioBtn8),"released", 699 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)8); 700 | radioBtn9 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn8), "24C256"); 701 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn9, FALSE, FALSE, 5); 702 | g_signal_connect(G_OBJECT(radioBtn9),"released", 703 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)9); 704 | radioBtn10 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn9), "24C512"); 705 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn10, FALSE, FALSE, 5); 706 | g_signal_connect(G_OBJECT(radioBtn10),"released", 707 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)10); 708 | radioBtn11 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn10), "24C1024"); 709 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn11, FALSE, FALSE, 5); 710 | g_signal_connect(G_OBJECT(radioBtn11),"released", 711 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)11); 712 | radioBtn12 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn11), "24C2048"); 713 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn12, FALSE, FALSE, 5); 714 | g_signal_connect(G_OBJECT(radioBtn12),"released", 715 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)12); 716 | radioBtn13 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioBtn12), "24C4096"); 717 | gtk_box_pack_start(GTK_BOX(vbox1), radioBtn13, FALSE, FALSE, 5); 718 | 719 | gtk_toggle_button_set_active(radioBtn4, TRUE); 720 | g_signal_connect(G_OBJECT(radioBtn13),"released", 721 | G_CALLBACK(On_Eeprom_Radio_Mode), (gpointer)13); 722 | vbox2 = gtk_vbox_new(FALSE, 0); 723 | gtk_box_pack_start(GTK_BOX(hbox), vbox2, FALSE, FALSE, 5); 724 | frame2 = gtk_frame_new("Write Data"); 725 | gtk_container_add(GTK_CONTAINER(vbox2), frame2); 726 | table = gtk_table_new(8, 6, TRUE); 727 | gtk_container_add(GTK_CONTAINER(frame2), table); 728 | label = gtk_label_new("Start Addr Of Data Unit:"); 729 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 3, 0, 1); 730 | entry_addr_I2c1 = gtk_entry_new(); 731 | gtk_table_attach_defaults(GTK_TABLE(table), entry_addr_I2c1, 0, 2, 1, 2); 732 | label = gtk_label_new("Write Length:"); 733 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 2, 3); 734 | entry_len_I2c1 = gtk_entry_new(); 735 | gtk_table_attach_defaults(GTK_TABLE(table), entry_len_I2c1, 0, 2, 3, 4); 736 | WrBtn = gtk_button_new_with_label(" Write "); 737 | gtk_table_attach_defaults(GTK_TABLE(table), WrBtn, 3, 4, 3, 4); 738 | label = gtk_label_new("Data Of Write:"); 739 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 4, 5); 740 | entry_data_I2c1 = gtk_entry_new(); 741 | gtk_table_attach_defaults(GTK_TABLE(table), entry_data_I2c1, 0, 5, 5, 6); 742 | g_signal_connect(G_OBJECT(WrBtn), "clicked", 743 | G_CALLBACK(CH34x_EEPROM_Write), (gpointer)entry_data_I2c1); 744 | 745 | frame3 = gtk_frame_new("Read Data"); 746 | gtk_container_add(GTK_CONTAINER(vbox2), frame3); 747 | table = gtk_table_new(8, 6, TRUE); 748 | gtk_container_add(GTK_CONTAINER(frame3), table); 749 | label = gtk_label_new("Start Addr Of Data Unit:"); 750 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 3, 0, 1); 751 | entry_addr_I2c2 = gtk_entry_new(); 752 | gtk_table_attach_defaults(GTK_TABLE(table), entry_addr_I2c2, 0, 2, 1, 2); 753 | label = gtk_label_new("Read Length:"); 754 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 2, 3); 755 | entry_len_I2c2 = gtk_entry_new(); 756 | gtk_table_attach_defaults(GTK_TABLE(table), entry_len_I2c2, 0, 2, 3, 4); 757 | RdBtn = gtk_button_new_with_label(" Read "); 758 | gtk_table_attach_defaults(GTK_TABLE(table), RdBtn, 3, 4, 3, 4); 759 | label = gtk_label_new("Data Of Read:"); 760 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 4, 5); 761 | entry_data_I2c2 = gtk_entry_new(); 762 | gtk_table_attach_defaults(GTK_TABLE(table), entry_data_I2c2, 0, 5, 5, 6); 763 | g_signal_connect(G_OBJECT(RdBtn), "clicked", 764 | G_CALLBACK(CH34x_EEPROM_Read), (gpointer)entry_data_I2c2); 765 | 766 | // entry_data = gtk_text_view_new(); 767 | // buffer1 = gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry_data)); 768 | // scroll_window = gtk_scrolled_window_new(NULL, NULL); 769 | // gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window), 770 | // GTK_POLICY_NEVER, 771 | // GTK_POLICY_AUTOMATIC); 772 | // gtk_container_add(GTK_CONTAINER(scroll_window), entry_data); 773 | // gtk_table_attach_defaults(GTK_TABLE(table), scroll_window, 0, 6, 5, 8); 774 | // 775 | // insert_text(buffer1); 776 | 777 | 778 | label = gtk_label_new(buffer[2]); 779 | gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label); 780 | } 781 | 782 | //Falsh ReadByte 783 | BOOL CH34x_Flash_ReadByte( PUCHAR oBuffer, ULONG iAddr, ULONG iLength ) 784 | { 785 | ULONG mLen, iChipselect; 786 | mLen = iLength; 787 | iChipselect = 0x80; 788 | oBuffer[0] = ReadByte; 789 | oBuffer[1] = (UCHAR)( iAddr >> 16 & 0xff ); 790 | oBuffer[2] = (UCHAR)( iAddr >> 8 & 0xff ); 791 | oBuffer[3] = (UCHAR)( iAddr & 0xff ); 792 | if( CH34xStreamSPI4( iChipselect, mLen, oBuffer ) == false ) 793 | return false; 794 | return true; 795 | } 796 | 797 | //Write Enable 798 | BOOL CH34xWriteEnable() 799 | { 800 | ULONG mLen, iChipselect; 801 | UCHAR mWrBuf[2]; 802 | mWrBuf[0] = WREN; 803 | mLen = 2; 804 | iChipselect = 0x80; 805 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 806 | return false; 807 | else 808 | return true; 809 | } 810 | 811 | //Write wait 812 | BOOL CH34xFlash_Wait() 813 | { 814 | ULONG mLen, iChipselect; 815 | ULONG i = 0; 816 | UCHAR mWrBuf[3]; 817 | UCHAR status; 818 | mLen = 3; 819 | iChipselect = 0x80; 820 | mWrBuf[0] = RDSR; 821 | do{ 822 | mWrBuf[0] = RDSR; 823 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 824 | return false; 825 | status = mWrBuf[1]; 826 | }while( status & 1 ); 827 | return true; 828 | } 829 | 830 | //Sector Erase: Every 4K 831 | BOOL CH34xSectorErase( ULONG StartAddr ) 832 | { 833 | ULONG mLen, iChipselect; 834 | UCHAR mWrBuf[4]; 835 | if( CH34xWriteEnable() == false ) 836 | return false; 837 | mWrBuf[0] = Sector_Erase; 838 | mWrBuf[1] = (UCHAR)( StartAddr >> 16 & 0xff ); 839 | mWrBuf[2] = (UCHAR)( StartAddr >> 8 & 0xf0 ); 840 | mWrBuf[3] = 0x00; 841 | mLen = 4; 842 | iChipselect = 0x80; 843 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 844 | return false; 845 | 846 | if( CH34xFlash_Wait() == false ) 847 | return false; 848 | return true; 849 | } 850 | 851 | //Read Block Data 852 | BOOL CH34x_Flash_ReadBlock( PUCHAR oBuffer, ULONG iAddr, ULONG iLength ) 853 | { 854 | ULONG mLen, iChipselect; 855 | UCHAR mWrBuf[1028]; 856 | ULONG i; 857 | mLen = 1024; //Read length Once 858 | iChipselect = 0x80; 859 | iAddr = iAddr - iAddr % MAX_BUFFER_LENGTH; 860 | for( i=0; i < iLength;) 861 | { 862 | memset(mWrBuf, 0, sizeof(mWrBuf)); 863 | mWrBuf[0] = ReadByte; 864 | mWrBuf[1] = (UCHAR)( iAddr >> 16 & 0xff ); 865 | mWrBuf[2] = (UCHAR)( iAddr >> 8 & 0xff ); 866 | mWrBuf[3] = (UCHAR)( iAddr & 0xff ); 867 | if( CH34xStreamSPI4( iChipselect, mLen+4, mWrBuf ) == false ) 868 | return false; 869 | memcpy(oBuffer + i, &mWrBuf[4], 1024 * sizeof(unsigned char)); 870 | i = i + 1024; 871 | iAddr += 1024; 872 | } 873 | 874 | return true; 875 | } 876 | 877 | //Flash Read Status 878 | BOOL CH34xFlashReadStatus() 879 | { 880 | ULONG mLen, iChipselect; 881 | UCHAR status; 882 | UCHAR mWrBuf[3]; 883 | iChipselect = 0x80; 884 | mLen = 3; 885 | mWrBuf[0] = RDSR; 886 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 887 | return false; 888 | status = mWrBuf[1]; 889 | if( status & 0x0c ) 890 | { 891 | mWrBuf[0] = EWSR; 892 | mLen = 1; 893 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 894 | return false; 895 | mLen = 2; 896 | memset( mWrBuf, 0, sizeof( UCHAR ) * mLen ); 897 | mWrBuf[0] = WRSR; 898 | mWrBuf[1] = status & (~0x0c); 899 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 900 | return false; 901 | } 902 | mWrBuf[0] = RDSR; 903 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 904 | return false; 905 | status = mWrBuf[1]; 906 | return true; 907 | } 908 | 909 | // One Byte Write 910 | BOOL CH34x_Flash_Write( PVOID iBuffer, ULONG iAddr, ULONG iLength ) 911 | { 912 | ULONG i; 913 | ULONG iChipselect = 0x80; 914 | UCHAR mWrBuf[5]; 915 | ULONG mLen = 5; 916 | for( i = 0; i < iLength; i++ ) 917 | { 918 | if( !CH34xWriteEnable() ) 919 | return false; 920 | mWrBuf[0] = Byte_Program; 921 | mWrBuf[1] = (UCHAR)(iAddr >> 16 & 0xff); 922 | mWrBuf[2] = (UCHAR)(iAddr >> 8 & 0xff); 923 | mWrBuf[3] = (UCHAR)(iAddr & 0xff); 924 | iAddr++; 925 | mWrBuf[4] = *((PUCHAR)iBuffer + i); 926 | if( CH34xStreamSPI4( iChipselect, mLen, mWrBuf ) == false ) 927 | return false; 928 | memset( mWrBuf, 0, sizeof( UCHAR ) * mLen ); 929 | if( !CH34xFlash_Wait() ) 930 | return false; 931 | } 932 | return true; 933 | } 934 | 935 | //FLASH Mode: Write Block Data 936 | void CH34xWriteSPI(GtkWidget *Button, gpointer Data) 937 | { 938 | GtkWidget *label; 939 | int retval; 940 | unsigned char iBuffer[MAX_BUFFER_LENGTH]; 941 | unsigned char oBuffer[MAX_LENGTH]; 942 | unsigned long iLength = 0; 943 | unsigned int retual_length; 944 | unsigned long iAddr = 0; 945 | unsigned long Cur_state = 0; 946 | const unsigned char *len; 947 | unsigned char *Addr_tmp; 948 | unsigned char temp[10]; 949 | int i; 950 | 951 | memset(iBuffer, 0, sizeof(iBuffer)); 952 | memset(oBuffer, 0, sizeof(iBuffer)); 953 | memset(temp, 0, sizeof(temp)); 954 | Addr_tmp = gtk_entry_get_text(GTK_ENTRY(entry_addr_Flash1)); 955 | iAddr = char_to_hex(Addr_tmp); 956 | len = gtk_entry_get_text(GTK_ENTRY(entry_len_Flash1)); 957 | iLength = char_to_hex(len); 958 | retval = CH34xFlashReadStatus(); 959 | if( retval == false ) 960 | { 961 | printf("error in flash status\n"); 962 | goto error; 963 | } 964 | retval = CH34x_Flash_ReadBlock( iBuffer, iAddr, MAX_BUFFER_LENGTH ); 965 | if( retval == false ) 966 | { 967 | printf("error in flash ReadBlock\n"); 968 | goto error; 969 | } 970 | retval = CH34xSectorErase( iAddr ); 971 | if( retval == false ) 972 | { 973 | printf("error in flash Sector Erase\n"); 974 | goto error; 975 | } 976 | len = NULL; 977 | len = gtk_entry_get_text(GTK_ENTRY((GtkWidget *)Data)); 978 | retual_length = strlen((unsigned char *)len) % 2 == 0 ? strlen((unsigned char *)len) / 2 : (strlen((unsigned char *)len) / 2 + 1); 979 | hex_to_char(temp, retual_length); 980 | gtk_entry_set_text(GTK_ENTRY(entry_len_Flash1), temp); 981 | Cur_state = iAddr % MAX_BUFFER_LENGTH; 982 | string_to_char(len, oBuffer); 983 | for( i = 0; i < retual_length; i++ ) 984 | iBuffer[Cur_state + i] = oBuffer[i]; 985 | retval = CH34x_Flash_Write( iBuffer, (iAddr - iAddr % MAX_BUFFER_LENGTH), MAX_BUFFER_LENGTH ); 986 | if( retval == false ) 987 | { 988 | printf("error in flash Write\n"); 989 | goto error; 990 | } 991 | 992 | g_message("Success\n"); 993 | return; 994 | 995 | error: 996 | g_message("failed\n"); 997 | return; 998 | } 999 | 1000 | //FLASH MODE: Read Block Data 1001 | void CH34xReadSPI(GtkWidget *Button, gpointer Data) 1002 | { 1003 | unsigned long iLength = 0; 1004 | unsigned long iAddr; 1005 | unsigned char iBuffer[MAX_LENGTH] = {'\0'}; 1006 | const unsigned char *len; 1007 | unsigned char *Addr_tmp; 1008 | const char *ReadBuffer; 1009 | int retval; 1010 | int i; 1011 | ReadBuffer = (char*)malloc(sizeof(unsigned char) * DEFAULT_BUFFER_LEN); 1012 | Addr_tmp = gtk_entry_get_text(GTK_ENTRY(entry_addr_Flash2)); 1013 | iAddr = char_to_hex(Addr_tmp); 1014 | len = gtk_entry_get_text(GTK_ENTRY(entry_len_Flash2)); 1015 | iLength = char_to_hex(len); 1016 | retval = CH34x_Flash_ReadByte( iBuffer, iAddr, iLength + 4 ); 1017 | if( retval == false ) 1018 | { 1019 | printf("Read Flash Error\n"); 1020 | } 1021 | char_to_string(&iBuffer[4], ReadBuffer, iLength); 1022 | gtk_entry_set_text(GTK_ENTRY((GtkWidget *)Data), ReadBuffer); 1023 | free( ReadBuffer ); 1024 | } 1025 | 1026 | 1027 | void CH34x_SetOutput(GtkWidget *Button, gpointer Data) 1028 | { 1029 | unsigned long iEnable; 1030 | unsigned long iDirData; 1031 | unsigned long iConData; 1032 | int retval; 1033 | const char *len; 1034 | len = gtk_entry_get_text(GTK_ENTRY(entry_enable_Output)); 1035 | iEnable = char_to_hex(len); 1036 | len = gtk_entry_get_text(GTK_ENTRY(entry_dirdata_Output)); 1037 | iDirData = char_to_hex(len); 1038 | len = gtk_entry_get_text(GTK_ENTRY(entry_condata_Output)); 1039 | iConData = char_to_hex(len); 1040 | retval = CH34xSetOutput(iEnable, iDirData, iConData); 1041 | if( retval == false ) 1042 | { 1043 | printf("------>Set Output Error!\n"); 1044 | } 1045 | else printf("------>Set Output Success!\n"); 1046 | } 1047 | 1048 | 1049 | void CH34x_SetD5D0(GtkWidget *Button, gpointer Data) 1050 | { 1051 | unsigned char iDirData; 1052 | unsigned char iConData; 1053 | int retval; 1054 | const char *len; 1055 | len = gtk_entry_get_text(GTK_ENTRY(entry_dirdata_D5D0)); 1056 | iDirData = char_to_hex(len); 1057 | len = gtk_entry_get_text(GTK_ENTRY(entry_condata_D5D0)); 1058 | iConData = char_to_hex(len); 1059 | printf("iDirData:%.2x ", iDirData); 1060 | printf("iConData:%.2x ", iConData); 1061 | retval = CH34xSet_D5_D0(iDirData, iConData); 1062 | if( retval == false ) 1063 | { 1064 | printf("------>Set D5D0 Error!\n"); 1065 | } 1066 | else printf("------>Set D5D0 Success!\n"); 1067 | } 1068 | 1069 | 1070 | //FLASH MODE PAGE 1071 | void notebook_add_page4(GtkWidget *notebook, GtkWidget *frame) 1072 | { 1073 | GtkWidget *label; 1074 | GtkWidget *vbox; 1075 | GtkWidget *frame1; 1076 | GtkWidget *frame2; 1077 | GtkWidget *table; 1078 | GtkWidget *WrBtn; 1079 | GtkWidget *RdBtn; 1080 | 1081 | 1082 | vbox = gtk_vbox_new(FALSE, 0); 1083 | gtk_container_add(GTK_CONTAINER(frame), vbox); 1084 | frame1 = gtk_frame_new("Flash Write Data"); 1085 | gtk_container_add(GTK_CONTAINER(vbox), frame1); 1086 | table = gtk_table_new(8, 8, TRUE); 1087 | gtk_container_add(GTK_CONTAINER(frame1), table); 1088 | label = gtk_label_new("Start Addr Of Data Unit:"); 1089 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 3, 0, 1); 1090 | entry_addr_Flash1 = gtk_entry_new(); 1091 | gtk_table_attach_defaults(GTK_TABLE(table), entry_addr_Flash1, 0, 2, 1, 2); 1092 | label = gtk_label_new("Write Length:"); 1093 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 2, 3); 1094 | entry_len_Flash1 = gtk_entry_new(); 1095 | gtk_table_attach_defaults(GTK_TABLE(table), entry_len_Flash1, 0, 2, 3, 4); 1096 | WrBtn = gtk_button_new_with_label(" Write "); 1097 | gtk_table_attach_defaults(GTK_TABLE(table), WrBtn, 3, 4, 3, 4); 1098 | label = gtk_label_new("Data Of Write:"); 1099 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 4, 5); 1100 | entry_data_Flash1 = gtk_entry_new(); 1101 | gtk_table_attach_defaults(GTK_TABLE(table), entry_data_Flash1, 0, 6, 5, 6); 1102 | g_signal_connect(G_OBJECT(WrBtn), "clicked", 1103 | G_CALLBACK(CH34xWriteSPI), (gpointer)entry_data_Flash1); 1104 | 1105 | frame2 = gtk_frame_new("Flash Read Data"); 1106 | gtk_container_add(GTK_CONTAINER(vbox), frame2); 1107 | table = gtk_table_new(8, 8, TRUE); 1108 | gtk_container_add(GTK_CONTAINER(frame2), table); 1109 | label = gtk_label_new("Start Addr Of Data Unit:"); 1110 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 3, 0, 1); 1111 | entry_addr_Flash2 = gtk_entry_new(); 1112 | gtk_table_attach_defaults(GTK_TABLE(table), entry_addr_Flash2, 0, 2, 1, 2); 1113 | label = gtk_label_new("Read Length:"); 1114 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 2, 3); 1115 | entry_len_Flash2 = gtk_entry_new(); 1116 | gtk_table_attach_defaults(GTK_TABLE(table), entry_len_Flash2, 0, 2, 3, 4); 1117 | RdBtn = gtk_button_new_with_label(" Read "); 1118 | gtk_table_attach_defaults(GTK_TABLE(table), RdBtn, 3, 4, 3, 4); 1119 | label = gtk_label_new("Data Of Read:"); 1120 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 4, 5); 1121 | entry_data_Flash2 = gtk_entry_new(); 1122 | gtk_table_attach_defaults(GTK_TABLE(table), entry_data_Flash2, 0, 6, 5, 6); 1123 | g_signal_connect(G_OBJECT(RdBtn), "clicked", 1124 | G_CALLBACK(CH34xReadSPI), (gpointer)entry_data_Flash2); 1125 | 1126 | label = gtk_label_new(buffer[3]); 1127 | gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label); 1128 | } 1129 | 1130 | 1131 | void notebook_add_page5(GtkWidget *notebook, GtkWidget *frame) 1132 | { 1133 | GtkWidget *label; 1134 | GtkWidget *frame1; 1135 | GtkWidget *frame2; 1136 | GtkWidget *vbox; 1137 | GtkWidget *table; 1138 | GtkWidget *StBtnO; 1139 | GtkWidget *StBtnD; 1140 | 1141 | vbox = gtk_vbox_new(FALSE, 0); 1142 | gtk_container_add(GTK_CONTAINER(frame), vbox); 1143 | frame1 = gtk_frame_new("SET OUTPUT"); 1144 | gtk_box_pack_start(GTK_BOX(vbox), frame1, FALSE, FALSE, 5); 1145 | table = gtk_table_new(6, 6, TRUE); 1146 | gtk_container_add(GTK_CONTAINER(frame1), table); 1147 | label = gtk_label_new(" Bit7~Bit0<==>D7-D0, Bit8<==>ERR#, Bit9<==>PEMP, Bit10<==>INT#, Bit11<==>SLCT, Bit13<==>WAIT#, Bit14<==>DATAS#/READ#\n"\ 1148 | " Bit15<==>ADDRS#/ADDR/ALE, Bit16<==>RESET#, Bit17<==>WRITE#, Bit18<==>SCL, Bit29<==>SDA"); 1149 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 6, 0, 2); 1150 | 1151 | label = gtk_label_new("Enable :"); 1152 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 1153 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); 1154 | entry_enable_Output = gtk_entry_new(); 1155 | gtk_table_attach_defaults(GTK_TABLE(table), entry_enable_Output, 1, 2, 2, 3); 1156 | 1157 | label = gtk_label_new("DirData :"); 1158 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 1159 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4); 1160 | entry_dirdata_Output = gtk_entry_new(); 1161 | gtk_table_attach_defaults(GTK_TABLE(table), entry_dirdata_Output, 1, 2, 3, 4); 1162 | 1163 | label = gtk_label_new("ConData :"); 1164 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 1165 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 4, 5); 1166 | entry_condata_Output = gtk_entry_new(); 1167 | gtk_table_attach_defaults(GTK_TABLE(table), entry_condata_Output, 1, 2, 4, 5); 1168 | 1169 | StBtnO = gtk_button_new_with_label(" Set "); 1170 | gtk_table_attach_defaults(GTK_TABLE(table), StBtnO, 4, 5, 8, 9); 1171 | g_signal_connect(G_OBJECT(StBtnO), "clicked", 1172 | G_CALLBACK(CH34x_SetOutput), (gpointer)entry_enable_Output); 1173 | 1174 | frame2 = gtk_frame_new("Set D5D0"); 1175 | gtk_box_pack_start(GTK_BOX(vbox), frame2, FALSE, FALSE, 5); 1176 | table = gtk_table_new(6, 6, TRUE); 1177 | gtk_container_add(GTK_CONTAINER(frame2), table); 1178 | label = gtk_label_new("Bit5~Bit0<==>D5-D0" ); 1179 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 4, 0, 1); 1180 | 1181 | label = gtk_label_new("DirData :"); 1182 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 1183 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); 1184 | entry_dirdata_D5D0 = gtk_entry_new(); 1185 | gtk_table_attach_defaults(GTK_TABLE(table), entry_dirdata_D5D0, 1, 2, 2, 3); 1186 | 1187 | label = gtk_label_new("ConData :"); 1188 | gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT); 1189 | gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4); 1190 | entry_condata_D5D0 = gtk_entry_new(); 1191 | gtk_table_attach_defaults(GTK_TABLE(table), entry_condata_D5D0, 1, 2, 3, 4); 1192 | 1193 | StBtnD = gtk_button_new_with_label(" Set "); 1194 | gtk_table_attach_defaults(GTK_TABLE(table), StBtnD, 4, 5, 8, 9); 1195 | g_signal_connect(G_OBJECT(StBtnD), "clicked", 1196 | G_CALLBACK(CH34x_SetD5D0), (gpointer)entry_dirdata_D5D0); 1197 | 1198 | label = gtk_label_new(buffer[4]); 1199 | gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label); 1200 | } 1201 | 1202 | 1203 | //Second Window12120x12fff 1204 | GtkWidget *create_sub_window(GtkWidget *entry) 1205 | { 1206 | GtkWidget *sub_window; 1207 | GtkWidget *frame; 1208 | GtkWidget *label; 1209 | GtkWidget *notebook; 1210 | int retval, index; 1211 | 1212 | sub_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 1213 | g_signal_connect(G_OBJECT(sub_window), "delete_event", 1214 | G_CALLBACK(gtk_widget_destroy), sub_window); 1215 | gtk_window_set_title(GTK_WINDOW(sub_window), "WCH CH34x Debug"); 1216 | gtk_window_set_position(GTK_WINDOW(sub_window), GTK_WIN_POS_CENTER); 1217 | gtk_window_set_default_size(GTK_WINDOW(sub_window), 600, 600); 1218 | gtk_container_set_border_width(GTK_CONTAINER(sub_window), 10); 1219 | index = *(gtk_entry_get_text(GTK_ENTRY(entry))) - '1'; 1220 | retval = CH34xOpenDevice( index ); 1221 | if(!retval) 1222 | { 1223 | printf("Function Open Error\n"); 1224 | return NULL; 1225 | } 1226 | char *drv_version = (char *)malloc( sizeof( char ) * 30 ); 1227 | retval = CH34x_GetDrvVer( drv_version ); 1228 | if( retval == false ) 1229 | { 1230 | err( "CH34x_GetDrvVer Error" ); 1231 | return -1; 1232 | } 1233 | printf( "drv_version : %s\n", drv_version ); 1234 | free( drv_version ); 1235 | PUCHAR VendorId = (char *)malloc( sizeof(unsigned char)); 1236 | retval = CH34x_GetVendorId( VendorId ); 1237 | if( retval == false ) 1238 | { 1239 | err( "CH34x_GetVendorId Error" ); 1240 | return -1; 1241 | } 1242 | printf( "VendorId : 0x%02x\n", *VendorId ); 1243 | free( VendorId ); 1244 | notebook = gtk_notebook_new(); 1245 | gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook),GTK_POS_TOP); 1246 | gtk_container_add(GTK_CONTAINER(sub_window), notebook); 1247 | 1248 | frame = gtk_frame_new(bufferframe[0]); 1249 | gtk_widget_set_size_request(frame, 600, 500); 1250 | notebook_add_page1(notebook, frame); 1251 | frame = gtk_frame_new(bufferframe[1]); 1252 | gtk_widget_set_size_request(frame, 600, 500); 1253 | notebook_add_page2(notebook, frame); 1254 | frame = gtk_frame_new(bufferframe[2]); 1255 | gtk_widget_set_size_request(frame, 600, 500); 1256 | notebook_add_page3(notebook, frame); 1257 | frame = gtk_frame_new(bufferframe[3]); 1258 | gtk_widget_set_size_request(frame, 600, 500); 1259 | notebook_add_page4(notebook, frame); 1260 | frame = gtk_frame_new(bufferframe[4]); 1261 | gtk_widget_set_size_request(frame, 600, 500); 1262 | notebook_add_page5(notebook, frame); 1263 | g_signal_connect(G_OBJECT(sub_window), "destroy", 1264 | G_CALLBACK(gtk_destroy_sub_window), NULL); 1265 | gtk_widget_show_all(sub_window); 1266 | return sub_window; 1267 | } 1268 | 1269 | void gtk_show_sub(GtkWidget *button, gpointer data) 1270 | { 1271 | window_sub = create_sub_window((GtkWidget *)data); 1272 | } 1273 | 1274 | //Main Window 1275 | GtkWidget *create_main_window() 1276 | { 1277 | GtkWidget *window; 1278 | GtkWidget *vbox; 1279 | GtkWidget *hbox; 1280 | GtkWidget *label_dev_list; 1281 | GtkWidget *label_input; 1282 | GtkWidget *frame; 1283 | GtkWidget *entry_main; 1284 | GtkWidget *button_next; 1285 | GtkWidget *button_quit; 1286 | 1287 | int retval; 1288 | 1289 | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 1290 | gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); 1291 | gtk_window_set_default_size(GTK_WINDOW(window), 300, 100); 1292 | gtk_window_set_title(GTK_WINDOW(window), "WCH CH34x Chips Debug"); 1293 | 1294 | vbox = gtk_vbox_new(FALSE, 0); 1295 | gtk_container_add(GTK_CONTAINER(window), vbox); 1296 | frame = gtk_frame_new("Current CH34x Device List"); 1297 | 1298 | retval = get_ch34x_dev_list(); 1299 | if(retval == 0) 1300 | label_dev_list = gtk_label_new(gtk_dev_list); 1301 | else 1302 | label_dev_list = gtk_label_new("Can't find any devices"); 1303 | gtk_container_add(GTK_CONTAINER(frame), label_dev_list); 1304 | gtk_label_set_justify(GTK_LABEL(label_dev_list), GTK_JUSTIFY_LEFT); 1305 | gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); 1306 | 1307 | hbox = gtk_hbox_new(FALSE, 10); 1308 | gtk_container_set_border_width(GTK_CONTAINER(hbox), 10); 1309 | gtk_container_add(GTK_CONTAINER(vbox), hbox); 1310 | 1311 | label_input = gtk_label_new("Input Dev Num:"); 1312 | gtk_box_pack_start(GTK_BOX(hbox), label_input, FALSE, FALSE, 10); 1313 | 1314 | entry_main = gtk_entry_new(); 1315 | gtk_box_pack_start(GTK_BOX(hbox), entry_main, FALSE, FALSE, 10); 1316 | 1317 | button_next = gtk_button_new_with_label("Next"); 1318 | gtk_box_pack_start(GTK_BOX(hbox), button_next, FALSE, FALSE, 10); 1319 | 1320 | button_quit = gtk_button_new_with_label("Quit"); 1321 | gtk_box_pack_start(GTK_BOX(hbox), button_quit, TRUE, TRUE, 10); 1322 | 1323 | gtk_widget_show_all(window); 1324 | g_signal_connect(G_OBJECT(button_next), "clicked", 1325 | G_CALLBACK(gtk_show_sub), entry_main); 1326 | g_signal_connect(G_OBJECT(button_quit), "clicked", 1327 | G_CALLBACK(gtk_main_quit), NULL); 1328 | g_signal_connect(G_OBJECT(window), "destroy", 1329 | G_CALLBACK(gtk_main_quit), NULL); 1330 | return window; 1331 | } 1332 | 1333 | int main(int argc, char *argv[]) 1334 | { 1335 | gtk_init(&argc, &argv); 1336 | window_main = create_main_window(); 1337 | gtk_widget_show(window_main); 1338 | gtk_main(); 1339 | return 0; 1340 | } 1341 | 1342 | 1343 | --------------------------------------------------------------------------------