summaryrefslogtreecommitdiff
path: root/class/serial/usbh_ftdi.h
blob: 0d176299ee5d7fba35ad38b88a356a3dbe7f1dca (plain)
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
/*
 * Copyright (c) 2024 ~ 2025, sakumisu
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#ifndef USBH_FTDI_H
#define USBH_FTDI_H

#include "usb_cdc.h"

#define FTDI_VID 0x0403 /* Vendor Id */

/* FTDI device PIDs */
#define FTDI_8U232AM_PID     0x6001 /* Similar device to SIO above */
#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
#define FTDI_8U2232C_PID     0x6010 /* Dual channel device */
#define FTDI_4232H_PID       0x6011 /* Quad channel hi-speed device */
#define FTDI_232H_PID        0x6014 /* Single channel hi-speed device */
#define FTDI_FTX_PID         0x6015 /* FT-X series (FT201X, FT230X, FT231X, etc) */
#define FTDI_FT2233HP_PID    0x6040 /* Dual channel hi-speed device with PD */
#define FTDI_FT4233HP_PID    0x6041 /* Quad channel hi-speed device with PD */
#define FTDI_FT2232HP_PID    0x6042 /* Dual channel hi-speed device with PD */
#define FTDI_FT4232HP_PID    0x6043 /* Quad channel hi-speed device with PD */
#define FTDI_FT233HP_PID     0x6044 /* Dual channel hi-speed device with PD */
#define FTDI_FT232HP_PID     0x6045 /* Dual channel hi-speed device with PD */
#define FTDI_FT4232HA_PID    0x6048 /* Quad channel automotive grade hi-speed device */
#define FTDI_SIO_PID         0x8372 /* Product Id SIO application of 8U100AX */
#define FTDI_232RL_PID       0xFBFA /* Product ID for FT232RL */

/* Requests */
#define FTDI_SIO_RESET             0x00 /* Reset the port */
#define FTDI_SIO_SET_MODEM_CTRL    0x01 /* Set the modem control register */
#define FTDI_SIO_SET_FLOW_CTRL     0x02 /* Set flow control register */
#define FTDI_SIO_SET_BAUDRATE      0x03 /* Set baud rate */
#define FTDI_SIO_SET_DATA          0x04 /* Set the data characteristics of the port */
#define FTDI_SIO_GET_MODEM_STATUS  0x05
#define FTDI_SIO_SET_EVENT_CHAR    0x06
#define FTDI_SIO_SET_ERROR_CHAR    0x07
#define FTDI_SIO_SET_LATENCY_TIMER 0x09
#define FTDI_SIO_GET_LATENCY_TIMER 0x0A
#define FTDI_SIO_SET_BITMODE       0x0B
#define FTDI_SIO_READ_PINS         0x0C
#define FTDI_SIO_READ_EEPROM       0x90
#define FTDI_SIO_WRITE_EEPROM      0x91
#define FTDI_SIO_ERASE_EEPROM      0x92

/* Channel indices for FT2232, FT2232H and FT4232H devices */
#define FTDI_SIO_CHANNEL_A 1
#define FTDI_SIO_CHANNEL_B 2
#define FTDI_SIO_CHANNEL_C 3
#define FTDI_SIO_CHANNEL_D 4

/*
 * BmRequestType:  0100 0000B
 * bRequest:       FTDI_SIO_RESET
 * wValue:         Control Value
 *                   0 = Reset SIO
 *                   1 = Purge RX buffer
 *                   2 = Purge TX buffer
 * wIndex:         Port
 * wLength:        0
 * Data:           None
 *
 * The Reset SIO command has this effect:
 *
 *    Sets flow control set to 'none'
 *    Event char = $0D
 *    Event trigger = disabled
 *    Purge RX buffer
 *    Purge TX buffer
 *    Clear DTR
 *    Clear RTS
 *    baud and data format not reset
 *
 * The Purge RX and TX buffer commands affect nothing except the buffers
 *
   */

#define FTDI_SIO_RESET_SIO      0
#define FTDI_SIO_RESET_PURGE_RX 1
#define FTDI_SIO_RESET_PURGE_TX 2

/*
 * BmRequestType:  0100 0000B
 * bRequest:       FTDI_SIO_SET_BAUDRATE
 * wValue:         BaudDivisor value - see below
 * wIndex:         Port
 * wLength:        0
 * Data:           None
 * The BaudDivisor values are calculated as follows:
 * - BaseClock is either 12000000 or 48000000 depending on the device.
 *   FIXME: I wish I knew how to detect old chips to select proper base clock!
 * - BaudDivisor is a fixed point number encoded in a funny way.
 *   (--WRONG WAY OF THINKING--)
 *   BaudDivisor is a fixed point number encoded with following bit weighs:
 *   (-2)(-1)(13..0). It is a radical with a denominator of 4, so values
 *   end with 0.0 (00...), 0.25 (10...), 0.5 (01...), and 0.75 (11...).
 *   (--THE REALITY--)
 *   The both-bits-set has quite different meaning from 0.75 - the chip
 *   designers have decided it to mean 0.125 instead of 0.75.
 *   This info looked up in FTDI application note "FT8U232 DEVICES \ Data Rates
 *   and Flow Control Consideration for USB to RS232".
 * - BaudDivisor = (BaseClock / 16) / BaudRate, where the (=) operation should
 *   automagically re-encode the resulting value to take fractions into
 *   consideration.
 * As all values are integers, some bit twiddling is in order:
 *   BaudDivisor = (BaseClock / 16 / BaudRate) |
 *   (((BaseClock / 2 / BaudRate) & 4) ? 0x4000    // 0.5
 *    : ((BaseClock / 2 / BaudRate) & 2) ? 0x8000  // 0.25
 *    : ((BaseClock / 2 / BaudRate) & 1) ? 0xc000  // 0.125
 *    : 0)
 *
 * For the FT232BM, a 17th divisor bit was introduced to encode the multiples
 * of 0.125 missing from the FT8U232AM.  Bits 16 to 14 are coded as follows
 * (the first four codes are the same as for the FT8U232AM, where bit 16 is
 * always 0):
 *   000 - add .000 to divisor
 *   001 - add .500 to divisor
 *   010 - add .250 to divisor
 *   011 - add .125 to divisor
 *   100 - add .375 to divisor
 *   101 - add .625 to divisor
 *   110 - add .750 to divisor
 *   111 - add .875 to divisor
 * Bits 15 to 0 of the 17-bit divisor are placed in the urb value.  Bit 16 is
 * placed in bit 0 of the urb index.
 *
 * Note that there are a couple of special cases to support the highest baud
 * rates.  If the calculated divisor value is 1, this needs to be replaced with
 * 0.  Additionally for the FT232BM, if the calculated divisor value is 0x4001
 * (1.5), this needs to be replaced with 0x0001 (1) (but this divisor value is
 * not supported by the FT8U232AM).
 */

enum ftdi_sio_baudrate {
    ftdi_sio_b300 = 0,
    ftdi_sio_b600 = 1,
    ftdi_sio_b1200 = 2,
    ftdi_sio_b2400 = 3,
    ftdi_sio_b4800 = 4,
    ftdi_sio_b9600 = 5,
    ftdi_sio_b19200 = 6,
    ftdi_sio_b38400 = 7,
    ftdi_sio_b57600 = 8,
    ftdi_sio_b115200 = 9
};

/*
 * BmRequestType:  0100 0000B
 * bRequest:       FTDI_SIO_SET_DATA
 * wValue:         Data characteristics (see below)
 * wIndex:         Port
 * wLength:        0
 * Data:           No
 *
 * Data characteristics
 *
 *   B0..7   Number of data bits
 *   B8..10  Parity
 *           0 = None
 *           1 = Odd
 *           2 = Even
 *           3 = Mark
 *           4 = Space
 *   B11..13 Stop Bits
 *           0 = 1
 *           1 = 1.5
 *           2 = 2
 *   B14
 *           1 = TX ON (break)
 *           0 = TX OFF (normal state)
 *   B15 Reserved
 *
 */

#define FTDI_SIO_SET_DATA_PARITY_NONE  (0x0 << 8)
#define FTDI_SIO_SET_DATA_PARITY_ODD   (0x1 << 8)
#define FTDI_SIO_SET_DATA_PARITY_EVEN  (0x2 << 8)
#define FTDI_SIO_SET_DATA_PARITY_MARK  (0x3 << 8)
#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8)
#define FTDI_SIO_SET_DATA_STOP_BITS_1  (0x0 << 11)
#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11)
#define FTDI_SIO_SET_DATA_STOP_BITS_2  (0x2 << 11)
#define FTDI_SIO_SET_BREAK             (0x1 << 14)

/*
 * BmRequestType:   0100 0000B
 * bRequest:        FTDI_SIO_MODEM_CTRL
 * wValue:          ControlValue (see below)
 * wIndex:          Port
 * wLength:         0
 * Data:            None
 *
 * NOTE: If the device is in RTS/CTS flow control, the RTS set by this
 * command will be IGNORED without an error being returned
 * Also - you can not set DTR and RTS with one control message
 *
 * ControlValue
 * B0    DTR state
 *          0 = reset
 *          1 = set
 * B1    RTS state
 *          0 = reset
 *          1 = set
 * B2..7 Reserved
 * B8    DTR state enable
 *          0 = ignore
 *          1 = use DTR state
 * B9    RTS state enable
 *          0 = ignore
 *          1 = use RTS state
 * B10..15 Reserved
 *
 */

#define FTDI_SIO_SET_DTR_MASK 0x1
#define FTDI_SIO_SET_DTR_HIGH ((FTDI_SIO_SET_DTR_MASK << 8) | 1)
#define FTDI_SIO_SET_DTR_LOW  ((FTDI_SIO_SET_DTR_MASK << 8) | 0)
#define FTDI_SIO_SET_RTS_MASK 0x2
#define FTDI_SIO_SET_RTS_HIGH ((FTDI_SIO_SET_RTS_MASK << 8) | 2)
#define FTDI_SIO_SET_RTS_LOW  ((FTDI_SIO_SET_RTS_MASK << 8) | 0)

/*
 *   BmRequestType:  0100 0000b
 *   bRequest:       FTDI_SIO_SET_FLOW_CTRL
 *   wValue:         Xoff/Xon
 *   wIndex:         Protocol/Port - hIndex is protocol / lIndex is port
 *   wLength:        0
 *   Data:           None
 *
 * hIndex protocol is:
 *   B0 Output handshaking using RTS/CTS
 *       0 = disabled
 *       1 = enabled
 *   B1 Output handshaking using DTR/DSR
 *       0 = disabled
 *       1 = enabled
 *   B2 Xon/Xoff handshaking
 *       0 = disabled
 *       1 = enabled
 *
 * A value of zero in the hIndex field disables handshaking
 *
 * If Xon/Xoff handshaking is specified, the hValue field should contain the
 * XOFF character and the lValue field contains the XON character.
 */

#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0
#define FTDI_SIO_RTS_CTS_HS        (0x1 << 8)
#define FTDI_SIO_DTR_DSR_HS        (0x2 << 8)
#define FTDI_SIO_XON_XOFF_HS       (0x4 << 8)

/*
 *   BmRequestType:   1100 0000b
 *   bRequest:        FTDI_SIO_GET_MODEM_STATUS
 *   wValue:          zero
 *   wIndex:          Port
 *   wLength:         1
 *   Data:            Status
 *
 * One byte of data is returned
 * B0..3 0
 * B4    CTS
 *         0 = inactive
 *         1 = active
 * B5    DSR
 *         0 = inactive
 *         1 = active
 * B6    Ring Indicator (RI)
 *         0 = inactive
 *         1 = active
 * B7    Receive Line Signal Detect (RLSD)
 *         0 = inactive
 *         1 = active
 */

#define FTDI_SIO_CTS_MASK  0x10
#define FTDI_SIO_DSR_MASK  0x20
#define FTDI_SIO_RI_MASK   0x40
#define FTDI_SIO_RLSD_MASK 0x80

/* Possible bitmodes for FTDI_SIO_SET_BITMODE_REQUEST */
#define FTDI_SIO_BITMODE_RESET 0x00
#define FTDI_SIO_BITMODE_CBUS  0x20

/*
 * IN Endpoint
 *
 * The device reserves the first two bytes of data on this endpoint to contain
 * the current values of the modem and line status registers. In the absence of
 * data, the device generates a message consisting of these two status bytes
 * every 40 ms
 *
 * Byte 0: Modem Status
 *
 * Offset	Description
 * B0	Reserved - must be 1
 * B1	Reserved - must be 0
 * B2	Reserved - must be 0
 * B3	Reserved - must be 0
 * B4	Clear to Send (CTS)
 * B5	Data Set Ready (DSR)
 * B6	Ring Indicator (RI)
 * B7	Receive Line Signal Detect (RLSD)
 *
 * Byte 1: Line Status
 *
 * Offset	Description
 * B0	Data Ready (DR)
 * B1	Overrun Error (OE)
 * B2	Parity Error (PE)
 * B3	Framing Error (FE)
 * B4	Break Interrupt (BI)
 * B5	Transmitter Holding Register (THRE)
 * B6	Transmitter Empty (TEMT)
 * B7	Error in RCVR FIFO
 *
 */
#define FTDI_RS0_CTS  (1 << 4)
#define FTDI_RS0_DSR  (1 << 5)
#define FTDI_RS0_RI   (1 << 6)
#define FTDI_RS0_RLSD (1 << 7)

#define FTDI_RS_DR   1
#define FTDI_RS_OE   (1 << 1)
#define FTDI_RS_PE   (1 << 2)
#define FTDI_RS_FE   (1 << 3)
#define FTDI_RS_BI   (1 << 4)
#define FTDI_RS_THRE (1 << 5)
#define FTDI_RS_TEMT (1 << 6)
#define FTDI_RS_FIFO (1 << 7)

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif

#endif /* USBH_FTDI_H */