File: ch341a.h

package info (click to toggle)
ponyprog 3.1.3%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 11,488 kB
  • sloc: cpp: 35,376; python: 981; sh: 565; makefile: 41; ansic: 38
file content (399 lines) | stat: -rw-r--r-- 13,987 bytes parent folder | download | duplicates (2)
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
//=========================================================================//
//                                                                         //
//  PonyProg - Serial Device Programmer                                    //
//                                                                         //
//  Copyright (C) 1997-2021   Claudio Lanconelli                           //
//                                                                         //
//  https://github.com/lancos/ponyprog                                     //
//                                                                         //
//  LibUSB implementation for PonyProg (C) 2019 Eduard Kalinowski          //
//                                                                         //
//  sources:                                                               //
//  Copyright (C) 2014 Pluto Yang (yangyj.ee@gmail.com)                    //
//  https://github.com/setarcos/ch341prog                                  //
//                                                                         //
//  Copyright (C) 2016 Eugene Hutorny (eugene@hutorny.in.ua)               //
//  https://github.com/hutorny/usbuart                                     //
//                                                                         //
//  Copyright (c) 2017 Gunar Schorcht (gunar@schorcht.net)                 //
//  https://github.com/gschorcht/spi-ch341-usb                             //
//  https://github.com/gschorcht/i2c-ch341-usb                             //
//                                                                         //
//  Copyright (c) 2018 Sarim Khan  (sarim2005@gmail.com)                   //
//  https://github.com/sarim/ch341a-bitbang-userland                       //
//                                                                         //
//-------------------------------------------------------------------------//
//                                                                         //
// This program is free software; you can redistribute it and/or           //
// modify it under the terms of the GNU  General Public License            //
// as published by the Free Software Foundation; either version2 of        //
// the License, or (at your option) any later version.                     //
//                                                                         //
// This program is distributed in the hope that it will be useful,         //
// but WITHOUT ANY WARRANTY; without even the implied warranty of          //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       //
// General Public License for more details.                                //
//                                                                         //
// You should have received a copy of the GNU  General Public License      //
// along with this program (see LICENSE);     if not, write to the         //
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //
//                                                                         //
//=========================================================================//

#ifndef __CH341_H__
#define __CH341_H__

#include <libusb-1.0/libusb.h>

#include <QObject>
#include <QTimer>

// #define    CONTROL_WRITE_ENDPOINT          0x02
// #define    CONTROL_READ_ENDPOINT           0x82


#define    MAX_EEPROM_SIZE              131072 /* For 24c1024*/

#define    DEFAULT_CONFIGURATION        0x01
#define    DEFAULT_TIMEOUT              300    // 300mS for USB timeouts

#if 0
#define    IN_BUF_SZ                    0x100
#define    EEPROM_WRITE_BUF_SZ          0x2b   // only for 24c64 / 24c32 ??
#define    EEPROM_READ_BULKIN_BUF_SZ    0x20
#define    EEPROM_READ_BULKOUT_BUF_SZ   0x65
#endif

#define    CH341_PACKET_LENGTH          0x20
#define    CH341_MAX_PACKETS            256
#define    CH341_MAX_PACKET_LEN         (CH341_PACKET_LENGTH * CH341_MAX_PACKETS)

#define    CH34x_VENDOR_ID1             0x4348
#define    CH34x_VENDOR_ID2             0x1A86

#define    CH341A_PRODUCT               0x5512 // for SPI, I2C 

#define    CH341_UART_PRODUCT           0x5523
#define    CH340_UART_PRODUCT           0x7523



#if 0

#define    CH341A_CMD_SET_OUTPUT        0xA1
#define    CH341A_CMD_IO_ADDR           0xA2
#define    CH341A_CMD_PRINT_OUT         0xA3
#define    CH341A_CMD_SPI_STREAM        0xA8
#define    CH341A_CMD_SIO_STREAM        0xA9
#define    CH341A_CMD_I2C_STREAM        0xAA
#define    CH341A_CMD_UIO_STREAM        0xAB

#define    CH341A_CMD_I2C_STM_STA       0x74
#define    CH341A_CMD_I2C_STM_STO       0x75
#define    CH341A_CMD_I2C_STM_OUT       0x80
#define    CH341A_CMD_I2C_STM_IN        0xC0
#define    CH341A_CMD_I2C_STM_MAX       ( min( 0x3F, CH341_PACKET_LENGTH ) )
#define    CH341A_CMD_I2C_STM_SET       0x60
#define    CH341A_CMD_I2C_STM_US        0x40
#define    CH341A_CMD_I2C_STM_MS        0x50
#define    CH341A_CMD_I2C_STM_DLY       0x0F
#define    CH341A_CMD_I2C_STM_END       0x00

// GPIO part
#define    CH341A_CMD_UIO_STM_IN        0x00
#define    CH341A_CMD_UIO_STM_DIR       0x40
#define    CH341A_CMD_UIO_STM_OUT       0x80
#define    CH341A_CMD_UIO_STM_US        0xC0
#define    CH341A_CMD_UIO_STM_END       0x20

#define    CH341A_STM_I2C_20K           0x00
#define    CH341A_STM_I2C_100K          0x01
#define    CH341A_STM_I2C_400K          0x02
#define    CH341A_STM_I2C_750K          0x03
#define    CH341A_STM_SPI_DBL           0x04

#endif


/*******************************/
/* baudrate calculation factor */
/*******************************/
#define    CH341_BPS_MOD_BASE           20000000
#define    CH341_BPS_MOD_BASE_OFS       1100

//Vendor define
#define    CH341_REQ_WRITE_TYPE         0x40
#define    CH341_REQ_READ_TYPE          0xC0


#define    CH341_REG_STAT               0x0706
#define    CH341_REG_BREAK              0x1805
#define    CH341_REG_LCR                0x2518
#define    CH341_REG_FLOW_CTRL          0x2727
#define    CH341_REG_BAUD1              0x1312
#define    CH341_REG_BAUD2              0x0f2c  /*is it right, or 0x0f14 ?? */

#define    CH341_RESET_VALUE            0x501f    /* line mode? */
#define    CH341_RESET_INDEX            0xd90a    /* baud rate? */

#define    CH341_REQ_READ_VERSION       0x5F
#define    CH341_REQ_WRITE_REG          0x9A
#define    CH341_REQ_READ_REG           0x95
#define    CH341_REQ_SERIAL_INIT        0xA1
#define    CH341_REQ_MODEM_CTRL         0xA4  /* DTR and RTS */

// ??? right
#define    CH341_NBREAK_BITS_REG        0x4001

#define    CH341_NBREAK_BITS_REG1       0x01
#define    CH341_NBREAK_BITS_REG2       0x40

#define    CH341_INPUT_BUF_SIZE         0x08

/* status returned in third interrupt answer byte, inverted in data
   from irq */
//For CMD 0xA4 CH341_REQ_MODEM_CTRL
#define    CH341_UART_CTS               0x01
#define    CH341_UART_DSR               0x02
#define    CH341_UART_RING              0x04
#define    CH341_UART_DCD               0x08
#define    CH341_BITS_MODEM_STAT        0x0f /* all bits */

#define    CH341_MULT_STAT              0x04 /* multiple status since last interrupt event */

#define    CH341_CONTROL_OUT            0x10 // TX
#define    CH341_CONTROL_DTR            0x20 // DTR, 1 << 5
#define    CH341_CONTROL_RTS            0x40 // RTS, 1 << 6

//Uart state
#define    CH341_UART_STATE             0x00
#define    CH341_UART_OVERRUN_ERROR     0x01
#define    CH341_UART_BREAK_ERROR       //no define
#define    CH341_UART_PARITY_ERROR      0x02
#define    CH341_UART_FRAME_ERROR       0x06
#define    CH341_UART_RECV_ERROR        0x02
#define    CH341_UART_STATE_TRANSIENT_MASK    0x07

// LCR
#define    CH341_LCR_ENABLE_RX          0x80
#define    CH341_LCR_ENABLE_TX          0x40
#define    CH341_LCR_MARK_SPACE         0x20
#define    CH341_LCR_PAR_EVEN           0x10
#define    CH341_LCR_ENABLE_PAR         0x08
#define    CH341_LCR_STOP_BITS_2        0x04
#define    CH341_LCR_CS8                0x03
#define    CH341_LCR_CS7                0x02
#define    CH341_LCR_CS6                0x01
#define    CH341_LCR_CS5                0x00

//Flow control values
#define    CH34X_FLOW_CONTROL_NONE      0x0000
#define    CH34X_FLOW_CONTROL_RTS_CTS   0x0101
#define    CH34X_FLOW_CONTROL_DSR_DTR   0x0202

//Port state
#if 0
#define    CH341A_PORTA_STATE            0x01
#define    CH341A_PORTB_STATE            0x02
#define    CH341A_PORTC_STATE            0x03
#endif

//CH34x Baud Rate
#define    CH341_BAUDRATE_FACTOR        1532620800
#define    CH341_BAUDRATE_DIVMAX        3

#define    CH341_DATA_IN                (0x2|LIBUSB_ENDPOINT_IN)
#define    CH341_DATA_OUT               (0x2|LIBUSB_ENDPOINT_OUT)
#define    CTRL_IN                      (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN )
#define    CTRL_OUT                     (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT )
//#define    CTRL_IN                      (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_INTERFACE)
//#define    CTRL_OUT                     (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT | LIBUSB_RECIPIENT_INTERFACE)
#define    DEFAULT_BAUD_RATE            9600


// das hier ausprobieren
#define    CONTROL_REQUEST_TYPE_IN     ( LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE )
#define    CONTROL_REQUEST_TYPE_OUT    ( LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE )

#define    MAX_CONTROL_IN_TRANSFER_SIZE 2
#define    MAX_CONTROL_OUT_TRANSFER_SIZE 2

#if 0
// CH341a READ EEPROM setup packet for the 24c64
//   this needs putting into a struct to allow convenient access to individual elements

#define CH341_EEPROM_READ_SETUP_CMD \
	"\xaa\x74\x83\xa0\x00\x00\x74\x81\xa1\xe0\x00\x00\x06\x04\x00\x00" \
	"\x00\x00\x00\x00\x40\x00\x00\x00\x11\x4d\x40\x77\xcd\xab\xba\xdc" \
	"\xaa\xe0\x00\x00\xc4\xf1\x12\x00\x11\x4d\x40\x77\xf0\xf1\x12\x00" \
	"\xd9\x8b\x41\x7e\x00\xf0\xfd\x7f\xf0\xf1\x12\x00\x5a\x88\x41\x7e" \
	"\xaa\xe0\x00\x00\x2a\x88\x41\x7e\x06\x04\x00\x00\x11\x4d\x40\x77" \
	"\xe8\xf3\x12\x00\x14\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" \
	"\xaa\xdf\xc0\x75\x00"

// for 24c64
#define CH341_EEPROM_READ_NEXT_CMD  \
	"\xaa\x74\x83\xa0\x00\x00\x74\x81\xa1\xe0\x00\x00\x10\x00\x00\x00" \
	"\x00\x00\x00\x00\x8c\xf1\x12\x00\x01\x00\x00\x00\x00\x00\x00\x00" \
	"\xaa\xe0\x00\x00\x4c\xf1\x12\x00\x5d\x22\xd7\x5a\xdc\xf1\x12\x00" \
	"\x8f\x04\x44\x7e\x30\x88\x41\x7e\xff\xff\xff\xff\x2a\x88\x41\x7e" \
	"\xaa\xe0\x00\x7e\x00\x00\x00\x00\x69\x0e\x3c\x00\x12\x01\x19\x00" \
	"\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9c\x2e\x68\x00" \
	"\xaa\xdf\xc0\x75\x00"

#define CH341_EEPROM_READ_CMD_SZ 0x65

#endif

#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))

class ch341;


class ch341 : public QObject
{
	Q_OBJECT

  public:
	ch341(QObject *parent = 0);
	~ch341();

	int32_t Open(uint16_t vid, uint16_t pid);
	void    SetVerbose(void);
	void    Close();
#if 0
	int32_t SetStream(uint32_t speed);
	int32_t SpiCapacity(void);
	int32_t SpiRead(uint8_t *buf, uint32_t add, uint32_t len);
	int32_t ReadStatus(void);
	int32_t WriteStatus(uint8_t status);
	int32_t EraseChip(void);
	int32_t SpiWrite(uint8_t *buf, uint32_t add, uint32_t len);
#endif

	int32_t Release(void);
#if 0
	int32_t readEEPROM(uint8_t *buffer, uint32_t bytestoread);
	int32_t writeEEPROM(uint8_t *buffer, uint32_t bytesum);
#endif
	int32_t SetBaudRate(int32_t baudRate);
	int32_t SetTimeouts(int16_t t);
	int32_t SetBreakControl(int32_t state);
	void    SetParity(uint8_t p);
	void    SetBits(uint8_t b);
	void    SetStops(uint8_t s);
	void    SetFlowControl(uint8_t f);
	int32_t SetDTR(int32_t dtr);
	int32_t SetRTS(int32_t dtr);
	int32_t GetDSR();
	int32_t GetCTS();
	int32_t SetRTSDTR(int state);
	int32_t SetConfigLCR();
	int32_t Probe();
	int32_t ClearChip();
	int32_t ResetChip();

// 	int32_t GetStatus();
	int32_t GetStatusRx();
	int32_t GetStatusTx();
// 	int32_t Read(uint8_t *buf, size_t len);
// 	int32_t Write(uint8_t *buf, size_t len);

	void    ReleaseInterface(void);
	void    CloseHandle();

  signals:
// 	void receivedData(uint8_t *data, size_t len);
	void breakChanged(bool set);

  public slots:
// 	void onRecieiveData(quint8 *data, qint16 len);
// 	void sendData(const uint8_t &data, size_t len);
	void triggerBreak(uint msecs);

  private slots:
	void breakTimeout();

  public:
	// for callback
	static int16_t read_completed;
	static int16_t write_completed;

	struct libusb_device_handle *devHandle;
//     struct libusb_transfer *ctrl_transfer;

  private:
	int32_t getModemState(void);
	int32_t setHandshakeByte(void);
	int32_t init();
// 	void    updateStatus();
	void    v_print(int mode, int len);
//     void    allocTransfer();


// 	int setAsync(unsigned char data);
#if 0
	void    updateStatus(uint8_t *data, size_t l);

	void    SpiChipSelect(uint8_t *ptr, bool selected);
	int32_t SpiStream(uint8_t *out, uint8_t *in, uint32_t len);
	int32_t usbTransfer(const char *func, uint8_t type, uint8_t *buf, int len);
#endif

  private:
	struct dv
	{
		uint8_t	dv_prescaler;
		uint8_t	dv_div;
		uint8_t	dv_mod;
	};

	struct uart_div
	{
		uint32_t dvr_high;
		uint32_t dvr_low;
		uint32_t dvr_base_clock;
		struct dv dvr_divider;
	};

	// MODEM output lines
	uint8_t dtr; // modem line
	uint8_t rts; // modem line

	uint8_t rtsCtsEnabled;
	uint8_t dtrDsrEnabled;

	// UART settings
	uint8_t parity;
	uint8_t bits;
	uint8_t stops;
	uint8_t flow_control;
	int32_t baudRate;
	int16_t timeout;

//     struct libusb_transfer *ctrl_transfer;

//     uint8_t ctrl_buf[LIBUSB_CONTROL_SETUP_SIZE];

	// MODEM input lines
	uint8_t    ctsState;
	uint8_t    dsrState;
	uint8_t    dcdState;
	uint8_t    ringState;

	uint8_t lcr; // line control register
	uint8_t lsr; // line status register
	uint8_t msr; // modem status register
	uint8_t mcr; // modem control register

	uint8_t dev_vers;

	bool verbose;

	QTimer *breakTimer;
	int force_stop = 0;
};


#endif