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
|
/*
* Copyright (c) 2025, sakumisu
* Copyright (c) 2025, MDLZCOOL
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBH_SERIAL_H
#define USBH_SERIAL_H
#include "usb_cdc.h"
#define USBH_SERIAL_CTRL_NOCACHE_OFFSET 0
#define USBH_SERIAL_CTRL_NOCACHE_SIZE 32
#define USBH_SERIAL_INT_NOCACHE_OFFSET USB_ALIGN_UP(USBH_SERIAL_CTRL_NOCACHE_SIZE, CONFIG_USB_ALIGN_SIZE)
#define USBH_SERIAL_INT_NOCACHE_SIZE 32
#define USBH_SERIAL_RX_NOCACHE_OFFSET USB_ALIGN_UP((USBH_SERIAL_INT_NOCACHE_OFFSET + USBH_SERIAL_INT_NOCACHE_SIZE), CONFIG_USB_ALIGN_SIZE)
#define USBH_SERIAL_RX_NOCACHE_SIZE 512
#define USBH_SERIAL_RX2_NOCACHE_OFFSET USB_ALIGN_UP((USBH_SERIAL_RX_NOCACHE_OFFSET + USBH_SERIAL_RX_NOCACHE_SIZE), CONFIG_USB_ALIGN_SIZE)
#define USBH_SERIAL_RX2_NOCACHE_SIZE 512
#define USBH_SERIAL_DATABITS_5 5
#define USBH_SERIAL_DATABITS_6 6
#define USBH_SERIAL_DATABITS_7 7
#define USBH_SERIAL_DATABITS_8 8
#define USBH_SERIAL_PARITY_NONE 0
#define USBH_SERIAL_PARITY_ODD 1
#define USBH_SERIAL_PARITY_EVEN 2
#define USBH_SERIAL_PARITY_MARK 3
#define USBH_SERIAL_PARITY_SPACE 4
#define USBH_SERIAL_STOPBITS_1 0
#define USBH_SERIAL_STOPBITS_1_5 1
#define USBH_SERIAL_STOPBITS_2 2
/* modem lines */
#define USBH_SERIAL_TIOCM_LE 0x001 /* line enable */
#define USBH_SERIAL_TIOCM_DTR 0x002 /* data terminal ready */
#define USBH_SERIAL_TIOCM_RTS 0x004 /* request to send */
#define USBH_SERIAL_TIOCM_ST 0x010 /* secondary transmit */
#define USBH_SERIAL_TIOCM_SR 0x020 /* secondary receive */
#define USBH_SERIAL_TIOCM_CTS 0x040 /* clear to send */
#define USBH_SERIAL_TIOCM_CAR 0x100 /* carrier detect */
#define USBH_SERIAL_TIOCM_CD USBH_SERIAL_TIOCM_CAR
#define USBH_SERIAL_TIOCM_RNG 0x200 /* ring */
#define USBH_SERIAL_TIOCM_RI USBH_SERIAL_TIOCM_RNG
#define USBH_SERIAL_TIOCM_DSR 0x400 /* data set ready */
#define USBH_SERIAL_TIOCM_OUT1 0x2000
#define USBH_SERIAL_TIOCM_OUT2 0x4000
#define USBH_SERIAL_TIOCM_LOOP 0x8000
#define USBH_SERIAL_O_RDONLY 0x0000 /* open for reading only */
#define USBH_SERIAL_O_WRONLY 0x0001 /* open for writing only */
#define USBH_SERIAL_O_RDWR 0x0002 /* open for reading and writing */
#define USBH_SERIAL_O_ACCMODE 0x0003 /* mask for above modes, from 4.4BSD https://minnie.tuhs.org/cgi-bin/utree.pl?file=4.4BSD/usr/include/sys/fcntl.h */
#define USBH_SERIAL_O_NONBLOCK 0x0004 /* non-blocking I/O, from BSD apple https://opensource.apple.com/source/xnu/xnu-1228.0.2/bsd/sys/fcntl.h */
#define USBH_SERIAL_CMD_SET_ATTR 0
#define USBH_SERIAL_CMD_GET_ATTR 1
#define USBH_SERIAL_CMD_IOCMBIS 2
#define USBH_SERIAL_CMD_IOCMBIC 3
#define USBH_SERIAL_CMD_TIOCMSET 4
#define USBH_SERIAL_CMD_TIOCMGET 5
#ifdef __cplusplus
extern "C" {
#endif
/*
* Counters of the input lines (CTS, DSR, RI, CD) interrupts
*/
struct usbh_serial_async_icount {
uint32_t cts, dsr, rng, dcd, tx, rx;
uint32_t frame, parity, overrun, brk;
uint32_t buf_overrun;
};
struct usbh_serial_termios {
uint32_t baudrate;
uint8_t databits;
uint8_t parity;
uint8_t stopbits;
bool rtscts; /* hardware flow control */
uint32_t rx_timeout;
};
struct usbh_serial;
typedef void (*usbh_serial_rx_complete_callback_t)(struct usbh_serial *serial, int nbytes);
/**
* @brief Serial Driver Operations
*/
struct usbh_serial_driver {
const char *driver_name;
uint8_t ignore_tx_header;
uint8_t ignore_rx_header;
int (*attach)(struct usbh_serial *serial);
void (*detach)(struct usbh_serial *serial);
int (*open)(struct usbh_serial *serial);
void (*close)(struct usbh_serial *serial);
int (*set_flow_control)(struct usbh_serial *serial, bool enable);
int (*set_line_coding)(struct usbh_serial *serial, struct cdc_line_coding *line_coding);
int (*get_line_coding)(struct usbh_serial *serial, struct cdc_line_coding *line_coding);
int (*set_line_state)(struct usbh_serial *serial, bool dtr, bool rts);
int (*get_modem_status)(struct usbh_serial *serial);
};
/**
* @brief Serial Instance
*/
struct usbh_serial {
struct usbh_hubport *hport;
uint8_t intf; /* Interface Number */
int minor; /* Serial Port Number (/dev/ttyUSBx or /dev/ttyACMx) */
int cdc_minor; /* Serial Port Number (/dev/ttyACMx) */
uint8_t *iobuffer; /* I/O buffer for serial transfers */
uint8_t ref_count; /* Reference Count */
uint32_t open_flags;
uint32_t rx_timeout_ms;
struct cdc_line_coding line_coding;
uint16_t line_state;
bool rtscts; /* hardware flow control */
struct usbh_serial_async_icount iocount;
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
struct usbh_urb bulkout_urb;
struct usbh_urb bulkin_urb;
const struct usbh_serial_driver *driver;
usb_ringbuffer_t rx_rb;
uint8_t rx_rb_pool[CONFIG_USBHOST_SERIAL_RX_SIZE];
usb_osal_sem_t rx_complete_sem;
uint8_t rx_buf_index;
int rx_errorcode;
usbh_serial_rx_complete_callback_t rx_complete_callback;
void *priv; /* Private Data */
void *user_data; /* User Data */
};
/* internal api */
struct usbh_serial *usbh_serial_probe(struct usbh_hubport *hport, uint8_t intf, const struct usbh_serial_driver *driver);
void usbh_serial_remove(struct usbh_serial *serial);
/* public api */
struct usbh_serial *usbh_serial_open(const char *devname, uint32_t open_flags);
int usbh_serial_close(struct usbh_serial *serial);
int usbh_serial_control(struct usbh_serial *serial, int cmd, void *arg);
int usbh_serial_write(struct usbh_serial *serial, const void *buffer, uint32_t buflen);
int usbh_serial_read(struct usbh_serial *serial, void *buffer, uint32_t buflen);
/* cdc only api */
int usbh_serial_cdc_write_async(struct usbh_serial *serial, uint8_t *buffer, uint32_t buflen, usbh_complete_callback_t complete, void *arg);
int usbh_serial_cdc_read_async(struct usbh_serial *serial, uint8_t *buffer, uint32_t buflen, usbh_complete_callback_t complete, void *arg);
/* public weak api */
void usbh_serial_run(struct usbh_serial *serial);
void usbh_serial_stop(struct usbh_serial *serial);
int usbh_serial(int argc, char **argv);
#ifdef __cplusplus
}
#endif
#endif /* USBH_SERIAL_H */
|