1 // Copyright 2019 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15
16
17 #include "esp_netif.h"
18 #include "esp_log.h"
19 #include "esp_netif_slip.h"
20 #include "esp_netif_lwip_internal.h"
21 #include "esp_netif_net_stack.h"
22
23 #ifdef CONFIG_ESP_NETIF_TCPIP_LWIP
24
25 #include "lwip/dns.h"
26 #include "lwip/opt.h"
27 #include "lwip/ip6_addr.h"
28 #include "lwip/netif.h"
29 #include "netif/slipif.h"
30 #include "lwip/sio.h"
31
32 #include <string.h>
33
34 static const char *TAG = "esp-netif_lwip-slip";
35
36 /**
37 * @brief LWIP SLIP context object extends esp-netif related data
38 */
39 typedef struct lwip_slip_ctx {
40 //! Generic esp-netif related data
41 netif_related_data_t base;
42
43 //! SLIP interface IP6 address
44 esp_ip6_addr_t addr;
45
46 } lwip_slip_ctx_t;
47
48 /**
49 * @brief Create a new lwip slip interface
50 */
esp_netif_new_slip(esp_netif_t * esp_netif,const esp_netif_netstack_config_t * esp_netif_stack_config)51 netif_related_data_t * esp_netif_new_slip(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config)
52 {
53 ESP_LOGD(TAG, "%s", __func__);
54
55 // Fetch netif and create context
56 struct netif *netif_impl = esp_netif->lwip_netif;
57
58 lwip_slip_ctx_t *slip_ctx = calloc(1, sizeof(lwip_slip_ctx_t));
59 if (slip_ctx == NULL) {
60 ESP_LOGE(TAG, "%s: cannot allocate lwip_slip_ctx_t", __func__);
61 return NULL;
62 }
63 // Setup the generic esp-netif fields
64 slip_ctx->base.is_point2point = true;
65 slip_ctx->base.netif_type = SLIP_LWIP_NETIF;
66
67 ESP_LOGD(TAG, "%s: Initialising SLIP (esp_netif %p, lwip_netif %p)", __func__, esp_netif, netif_impl);
68
69 ESP_LOGI(TAG, "%s: Created SLIP interface (netif %p, slip_ctx: %p)", __func__, esp_netif, slip_ctx);
70
71 return (netif_related_data_t *)slip_ctx;
72 }
73
74 /**
75 * @brief Stops the SLIP interface
76 */
esp_netif_stop_slip(esp_netif_t * esp_netif)77 esp_err_t esp_netif_stop_slip(esp_netif_t *esp_netif)
78 {
79 lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)esp_netif->related_data;
80 assert(slip_ctx->base.netif_type == SLIP_LWIP_NETIF);
81
82 ESP_LOGI(TAG, "%s: Stopped SLIP connection: %p", __func__, slip_ctx);
83
84 // Stop interface
85 netif_set_link_down(esp_netif->lwip_netif);
86
87 return ESP_OK;
88 }
89
90 /**
91 * @brief Starts the SLIP interface
92 */
esp_netif_start_slip(esp_netif_t * esp_netif)93 esp_err_t esp_netif_start_slip(esp_netif_t *esp_netif)
94 {
95 lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)esp_netif->related_data;
96 assert(slip_ctx->base.netif_type == SLIP_LWIP_NETIF);
97
98 ESP_LOGI(TAG, "%s: Starting SLIP interface: %p", __func__, slip_ctx);
99
100 // Set the netif up
101 netif_set_up(esp_netif->lwip_netif);
102 netif_set_link_up(esp_netif->lwip_netif);
103 #if CONFIG_LWIP_IPV6
104 int8_t addr_index = 0;
105
106 netif_ip6_addr_set(esp_netif->lwip_netif, addr_index, (ip6_addr_t *)&slip_ctx->addr);
107 netif_ip6_addr_set_state(esp_netif->lwip_netif, addr_index, IP6_ADDR_VALID);
108 #endif
109 return ESP_OK;
110 }
111
112
113 /**
114 * @brief Sets paramaters for the supplied netif
115 */
esp_netif_slip_set_params(esp_netif_t * netif,const esp_netif_slip_config_t * slip_config)116 esp_err_t esp_netif_slip_set_params(esp_netif_t *netif, const esp_netif_slip_config_t *slip_config)
117 {
118
119 lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)netif->related_data;
120 assert(slip_ctx->base.netif_type == SLIP_LWIP_NETIF);
121
122 ESP_LOGD(TAG, "%s (slip_ctx: %p)", __func__, slip_ctx);
123
124 if (netif_is_link_up(netif->lwip_netif)) {
125 ESP_LOGE(TAG, "Cannot set parameters while SLIP interface is running");
126 return ESP_ERR_INVALID_STATE;
127 }
128
129 memcpy(&slip_ctx->addr, &slip_config->ip6_addr, sizeof(esp_ip6_addr_t));
130
131
132 return ESP_OK;
133 }
134
135 #if CONFIG_LWIP_IPV6
esp_netif_slip_set_ipv6(esp_netif_t * netif,const esp_ip6_addr_t * ipv6)136 esp_err_t esp_netif_slip_set_ipv6(esp_netif_t *netif, const esp_ip6_addr_t *ipv6)
137 {
138 lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)netif->related_data;
139 assert(slip_ctx->base.netif_type == SLIP_LWIP_NETIF);
140
141 ESP_LOGV(TAG, "%s (slip_ctx: %p)", __func__, slip_ctx);
142
143 if (netif_is_link_up(netif->lwip_netif)) {
144 ESP_LOGE(TAG, "Cannot set parameters while SLIP interface is running");
145 return ESP_ERR_INVALID_STATE;
146 }
147 memcpy(&slip_ctx->addr, ipv6, sizeof(ip6_addr_t));
148 int8_t addr_index = 0;
149
150 netif_ip6_addr_set(netif->lwip_netif, addr_index, (ip6_addr_t *)&slip_ctx->addr);
151 netif_ip6_addr_set_state(netif->lwip_netif, addr_index, IP6_ADDR_VALID);
152
153 return ESP_OK;
154 }
155 #endif
156
157 /**
158 * @brief Write incoming serial data to the SLIP interface
159 */
esp_netif_lwip_slip_input(void * h,void * buffer,unsigned int len,void * eb)160 void esp_netif_lwip_slip_input(void *h, void *buffer, unsigned int len, void *eb)
161 {
162 esp_netif_t *netif = h;
163 lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)netif->related_data;
164 assert(slip_ctx->base.netif_type == SLIP_LWIP_NETIF);
165
166 ESP_LOGD(TAG, "%s", __func__);
167 ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG);
168
169 // Update slip netif with data
170 const int max_batch = 255;
171 int sent = 0;
172 while(sent < len) {
173 int batch = (len - sent) > max_batch ? max_batch : (len - sent);
174 slipif_received_bytes(netif->lwip_netif, buffer+sent, batch);
175 sent += batch;
176 }
177
178 // Process incoming bytes
179 for (int i = 0; i < len; i++) {
180 slipif_process_rxqueue(netif->lwip_netif);
181 }
182 }
183
184 /**
185 * @brief Write raw data out the SLIP interface
186 */
esp_netif_lwip_slip_raw_output(esp_netif_t * slip_netif,void * buffer,size_t len)187 void esp_netif_lwip_slip_raw_output(esp_netif_t *slip_netif, void *buffer, size_t len)
188 {
189 struct netif *lwip_netif = slip_netif->lwip_netif;
190
191 ESP_LOGD(TAG, "%s", __func__);
192
193 struct pbuf p = {
194 .next = NULL,
195 .payload = buffer,
196 .tot_len = len,
197 .len = len,
198 };
199
200 // Call slip if output function to feed data out slip interface
201 #if CONFIG_LWIP_IPV6
202 lwip_netif->output_ip6(lwip_netif, &p, NULL);
203 #else
204 lwip_netif->output(lwip_netif, &p, NULL);
205 #endif
206 }
207
208 /**
209 * @brief Destroys the SLIP context object
210 */
esp_netif_destroy_slip(netif_related_data_t * slip)211 void esp_netif_destroy_slip(netif_related_data_t *slip)
212 {
213 ESP_LOGD(TAG, "%s", __func__);
214
215 // Free base object
216 free(slip);
217 }
218
esp_slip_get_ip6(esp_netif_t * slip_netif)219 const esp_ip6_addr_t *esp_slip_get_ip6(esp_netif_t *slip_netif)
220 {
221 lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)slip_netif->related_data;
222 assert(slip_ctx->base.netif_type == SLIP_LWIP_NETIF);
223 return &slip_ctx->addr;
224 }
225
226 /** @brief Get esp-netif object corresponding to registration index
227 */
get_netif_with_esp_index(int index)228 static esp_netif_t * get_netif_with_esp_index(int index)
229 {
230 esp_netif_t *netif = NULL;
231 int counter = 0;
232 while ((netif = esp_netif_next(netif)) != NULL) {
233 if (counter == index) {
234 return netif;
235 }
236 counter++;
237 }
238 return NULL;
239 }
240
241 /** @brief Return list registration index of the supplied netif ptr
242 */
get_esp_netif_index(esp_netif_t * esp_netif)243 static int get_esp_netif_index(esp_netif_t * esp_netif)
244 {
245 esp_netif_t *netif = NULL;
246 int counter = 0;
247 while ((netif = esp_netif_next(netif)) != NULL) {
248 if (esp_netif == netif) {
249 return counter;
250 }
251 counter++;
252 }
253 return -1;
254 }
255
esp_slipif_init(struct netif * netif)256 err_t esp_slipif_init(struct netif *netif)
257 {
258 esp_netif_t *esp_netif = netif->state;
259 int esp_index = get_esp_netif_index(esp_netif);
260 if (esp_index < 0) {
261 return ERR_IF;
262 }
263
264 // Store netif index in net interface for SIO open command to abstract the dev
265 netif->state = (void *)esp_index;
266
267 return slipif_init(netif);
268 }
269
270 static const struct esp_netif_netstack_config s_netif_config_slip = {
271 .lwip = {
272 .init_fn = esp_slipif_init,
273 .input_fn = esp_netif_lwip_slip_input,
274 }
275 };
276
277 const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_slip = &s_netif_config_slip;
278
279
280 /***
281 * @brief Open a serial device for communication
282 */
sio_open(uint8_t devnum)283 sio_fd_t sio_open(uint8_t devnum)
284 {
285 ESP_LOGD(TAG, "Opening device: %d\r\n", devnum);
286
287 esp_netif_t *esp_netif = get_netif_with_esp_index(devnum);
288 if (!esp_netif) {
289 ESP_LOGE(TAG, "didn't find esp-netif with index=%d\n", devnum);
290 return NULL;
291 }
292
293 // Return SIO handle
294 return esp_netif;
295 }
296
297 /***
298 * @brief Send a single character to the serial device (blocking)
299 */
sio_send(uint8_t c,sio_fd_t fd)300 void sio_send(uint8_t c, sio_fd_t fd)
301 {
302 esp_netif_t *esp_netif = fd;
303
304 ESP_LOGD(TAG, "%s", __func__);
305 ESP_LOG_BUFFER_HEX_LEVEL(TAG, &c, 1, ESP_LOG_DEBUG);
306
307 esp_err_t ret = esp_netif_transmit(esp_netif, &c, 1);
308 if (ret != ESP_OK) {
309 // Handle errors
310 ESP_LOGD(TAG, "%s: uart_write_bytes error %i", __func__, ret);
311 }
312 }
313
314 #endif /* CONFIG_ESP_NETIF_TCPIP_LWIP */
315