-
Notifications
You must be signed in to change notification settings - Fork 1
/
net_w5500.h
290 lines (266 loc) · 9.83 KB
/
net_w5500.h
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
/* Copyright (C) 2014 David Zanetti
*
* This file is part of libkakapo.
*
* libkakapo is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License.
*
* libkakapo 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with libkapapo.
*
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NET_W5500_H_INCLUDED
#define NET_W5500_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
/** \file
* \brief W5500 driver public interface
*
* An implementation of a driver for the WizNet W5500 chip.
*
* WizNet W5500 implements a PHY, MAC, and IPv4 stack covering
* ICMP, TCP, UDP, and offers a RAW mode for custom protocol
* handling. Supports 8 sockets with a total of 32kB of SRAM.
*
* Sockets are read/write over a continual wrapping 64kB window
* mapped into the appropriate buffer space. No need to track
* MSS/MTU.
*
* Chip does NOT have a pre-programmed MAC, one must be supplied.
*
* http://www.wiznet.co.kr/w5500
*/
/** \brief W5500 socket protocol/mode */
typedef enum {
w5500_tcp, /**< Socket protocol is TCP */
w5500_udp, /**< Socket protocol is UDP */
w5500_macraw, /**< Socket "protocol" is MACRAW mode */
} w5500_sockmode_t;
/** \brief Event types from sockets for callbacks */
typedef enum {
w5500_accept = 0, /**< Socket has accepted a connection, TCP only */
w5500_rx, /**< Some data has been recieved */
w5500_dc, /**< Peer closed socket, TCP only */
} w5500_event_t;
/** \brief Initalise a W5500 chip
*
* \param spi_port SPI port to initalise and use
* \param cs_port HW port where CS pin is
* \param cs_pin Pin to use
* \param mac[6] MAC address to initalise with
* \return 0 on success, errors.h otherwise
*/
int w5500_init(spi_portname_t spi_port, PORT_t *cs_port, uint8_t cs_pin,
uint8_t *mac);
/** \brief W5500 IPv4 configuration
*
* \param ip[4] IP Address
* \param mask_cidr Netmask in CIDR notation
* \param gw[4] Gateway IP Address
* \return 0 on success, errors.h otherwise
*/
int w5500_ip_conf(uint8_t *ip, uint8_t mask_cidr, uint8_t *gw);
/** \brief W5500 Socket initalisation
*
* Sockets have a mode, and a size in kB for their tx and rx circular buffer.
* Note that the sum of RX buffers cannot exceed 16kB, same for TX buffers
*
* \param socknum Socket number (from zero)
* \param rxsize Size of circular buffer for RX, must be pow 2 =<16kB
* \param txsize Size of circular buffer for TX, must be pow 2 =<16kB
* \return 0 on success, errors.h otherwise
*/
int w5500_socket_init(uint8_t socknum, uint16_t rxsize, uint16_t txsize);
/** \brief Listen for a TCP connection
*
* The socket is configured to listen for and accept connections on the given
* port. Two hooks are provided fired when the connection is accepted, and when
* there has been additional packets recieved from the port. They must return
* void and accept a single uint8_t argument, the socket number which fired
* the event.
*
* \param socknum Socket number (from zero)
* \param port Port to listen on
* \param accept_fn Function hook to fire on new connection accepted
* \param rx_fn Function hook to fire when more data has been received
* \return 0 on success, errors.h otherwise
*/
int w5500_tcp_listen(uint8_t socknum, uint16_t port,
void (*event_fn)(uint8_t,w5500_event_t));
/** \brief Establish TCP connection
*
* The socket is prepared for TCP and connection to the address/port
* given is attempted. This will randomly select an unused source port
* on our end in the range 1024-65535
*
* \param socknum Socket number (from zero)
* \param addr[4] IPv4 address
* \param port Destination port
* \param rx_fn Callback function for this socket to have readable data
* \return 0 on success, errors.h otherwise
*/
int w5500_tcp_connect(uint8_t socknum, uint8_t *addr, uint16_t port,
void (*event_fn)(uint8_t,w5500_event_t));
/** \brief Disconnect TCP connection
*
* The socket is disconnected, gracefully where possible. The chip
* will automatically force to closed if a timeout expires.
*
* Note: we don't report if the close was clean or not.
*
* \param socknum Socket number (from zero)
* \return 0 on success, errors.h otherwise.
*/
int w5500_tcp_close(uint8_t socknum);
/** \brief Map a socket to a FILE stream.
*
* This should be called on each physical socket ONLY ONCE. The
* code will handle the fact the socket is closed, so you don't
* need to keep creating a map for each new connection.
*
* Call this after the socket has been prepared by
* w5500_socket_init(). You probably want to call this after
* usart init since otherwise it'll end up as stdin/stdout!
*
* Note: this assumes TCP mode for the socket, which you may
* not have set yet.
*
* Note: See connect and listen functions for interrupt callbacks.
*
* \param socknum Socket number (from zero)
* \param bufsize Internal buffer size. Used to reduce overhead
* from commands over SPI.
* \return FILE pointer, or NULL if failed
*/
FILE *w5500_tcp_map_stdio(uint8_t socknum, uint16_t bufsize);
/** \brief Check to see if a socket has waiting RX
*
* This is primarily so that rather than constantly polling gets()
* you can quickly check what is left to read.
*
* Note that this returns the combination of whatever is buffered
* plus the chip RX buffer, since we read lumps of bufsize data
* from the chip.
*
* \param socknum Socket number to check
* \return characters able to be read from the socket
*/
uint16_t w5500_tcp_unread(uint8_t socknum);
/** \brief Check to see how much space we have available in
* a socket to write into.
*
* This includes characters already buffered inside the the stdio
* layer since we will want to commit those at some point.
*
* \param socknum Socket number to check
* \return characters able to be written to the socket
*/
uint16_t w5500_tcp_writable(uint8_t socknum);
/** \brief Force a TCP socket to push data out.
*
* This performs two functions. Firstly it flushes the
* internal tx buffer from stdio layer to the chip.
* It also forces the chip to send immediately, rather
* than wait for a full MSS sized packet.
*
* \param socknum Socket number to push
* \return 0 on success, errors.h otherwise
*/
int w5500_tcp_push(uint8_t socknum);
/** \brief Listen on a UDP port.
*
* UDP, regardless of direction, is always listen based on our end. We open
* a port to accept UDP packets or send packets from.
*
* \param socknum Socket number to use (must have been init'd before)
* \param port Port on our end
* \param rx_fn Callback to make when a packet is recieved
* \return 0 on success, errors.h otherwise
*/
int w5500_udp_listen(uint8_t socknum, uint16_t port, void (*event_fn)(uint8_t,w5500_event_t));
/** \brief Retrieve UDP packet metadata
*
* Since UDP packets could come from anywhere into our socket, the chip
* prepends metadata (source ip, source port, and length) to the actual
* payload from the UDP packet.
*
* Note that if you get -EIO from this, then it's very likely the UDP socket
* is broken in some way, and it'll be closed automatically.
*
* \param socknum Socket number to use (must have been udp_listen before)
* \param ip[4] Buffer to write far IP address into (4 bytes)
* \param port Buffer to write far port into (2 bytes)
* \param len Buffer to write far paylong length into (2 bytes)
* \return 0 on success, errors.h otherwise
*/
int w5500_udp_rxmeta(uint8_t socknum, uint8_t *ip, uint16_t *port, uint16_t *len);
/** \brief Retrieve UDP payload
*
* Copies len bytes into the buffer passed. If buf is NULL, this has the effect
* of discarding that number of bytes. If there are insufficient bytes, it will
* copy what is available and return that length.
*
* Note: this MUST be called after the metadata is obtained, otherwise it has
* no idea what the length available is.
*
* \param socknum Socket number to use
* \param len Length of bytes to read
* \param buf[] Pointer to buffer to write to (may be NULL)
* \return actual number of bytes provided
*/
int w5500_udp_read(uint8_t socknum, uint16_t len, void *buf);
/** \brief Close a UDP listener
*
* Just closes the socket. This is not graceful since UDP isn't graceful. :)
*
* \param socknum Socket number to close
* \return 0 on success, errors.h otherwise
*/
int w5500_udp_close(uint8_t socknum);
/** \brief Write to a UDP socket buffer
*
* This writes out packet data but does not send it (you need udp_send for
* that.
*
* \param socknum Socket number to use
* \param len Length of the data to buffer
* \param buf[] Pointer to the buffer to read from
* \return 0 on success, errors.h otherwise
*/
int w5500_udp_write(uint8_t socknum, uint16_t len, void *buf);
/** \brief Send the current UDP packet buffer
*
* This performs the actual UDP packet send. It should only ever send
* one packet.
*
* Note: on error, this DOES NOT close the socket. You have to clean up
* this state yourself.
*
* \param socknum Socket number to use
* \param ip[4] IP address to send to
* \param port UDP port to send to
* \return 0 on success, errors.h otherwise.
*/
int w5500_udp_send(uint8_t socknum, uint8_t *ip, uint16_t port);
/** \brief Poll for events from the W5500 chip
*
* This will check for certain events on the chip and make the appropriate
* callbacks on sockets or global chip configuration.
*
* Generally this should be called when the HW interrupt line is asserted,
* but can be polled as you see fit.
*/
void w5500_poll(void);
#ifdef __cplusplus
}
#endif
#endif // NET_W5500_H_INCLUDED