1 /*
2 * Copyright (C) 2020-2022 Alibaba Group Holding Limited
3 */
4
5 #include <string.h>
6 #include "k_api.h"
7 #include "aos/kernel.h"
8
9 #include "lwip/err.h"
10 #include "lwip/netif.h"
11 #include "lwip/tcpip.h"
12 #include "lwip/ip_addr.h"
13 #include "netif/etharp.h"
14
15 #include "uservice/uservice.h"
16 #include "uservice/eventid.h"
17 #include "ulog/ulog.h"
18
19 #include "ch395_spi.h"
20 #include "ch395_cmd.h"
21 /* Private typedef -----------------------------------------------------------*/
22 typedef struct {
23 ip4_addr_t ip;
24 ip4_addr_t netmask;
25 ip4_addr_t gw;
26 } tcpip_ip_info_t;
27
28 /* Private define ------------------------------------------------------------*/
29 /* Stack size of the interface thread */
30 #define CH395_TASK_PRIO 20
31 #define CH395_TASK_SIZE (6 * 1024)
32 #define CH395_MAX_DATA_SIZE 1514 /*max size is 1514 */
33 #define CH395_MIN_DATA_SZIE 60 /*min size is 64 include 4 bytes crc*/
34
35 /* Define those to better describe your network interface. */
36 #define IFNAME0 'e'
37 #define IFNAME1 'n'
38
39 #define TAG "ch395_lwip"
40
41 static struct netif eth_lwip_netif;
42 static tcpip_ip_info_t eth_ip_info = {0};
43 static aos_task_t gst_ch395_lwip_int_task = {0};
44 static aos_task_t gst_ch395_input_task = {0};
45 static aos_sem_t gst_ch395_recv_sem = {0};
46 static st_ch395_info_t gst_lwipch395info = {0};
47
48 static void ch395_lwip_inter_proc(void);
49 static int ch395_eth_sock_macraw(void);
50
dump_ch395_packet(char * buf,int len)51 static void dump_ch395_packet(char *buf, int len)
52 {
53 int i = 0;
54 for (i = 0; i < len; i++) {
55 printf("0x%02x ", buf[i]);
56 if ((i + 1) % 32 == 0) {
57 printf("\r\n");
58 }
59 }
60 printf("\r\n");
61 }
62
low_level_output(struct netif * netif,struct pbuf * p)63 static err_t low_level_output(struct netif *netif, struct pbuf *p)
64 {
65 struct pbuf *q = NULL;
66 uint8_t *data = NULL;
67 uint32_t datalen = 0;
68 int32_t ret = 0;
69 uint32_t first_copy = 0;
70 uint32_t copylen = 0;
71 void *src_buf = NULL;
72
73 data = aos_malloc(CH395_MAX_DATA_SIZE);
74 memset(data, 0, CH395_MAX_DATA_SIZE);
75
76 for (q = p; q != NULL; q = q->next) {
77 src_buf = q->payload;
78 copylen = q->len;
79 if (first_copy == 0) {
80 src_buf = (char *)src_buf + ETH_PAD_SIZE;
81 copylen = copylen - ETH_PAD_SIZE;
82 first_copy = 1;
83 }
84
85 if (datalen + copylen >= CH395_MAX_DATA_SIZE) {
86 aos_free(data);
87 return ERR_BUF;
88 }
89 memcpy(&data[datalen], src_buf, copylen);
90 datalen = datalen + copylen;
91 }
92
93 if (datalen < CH395_MIN_DATA_SZIE) {
94 datalen = CH395_MIN_DATA_SZIE;
95 }
96 /*for 4-byte alignment, 14 bytes ethernet header will cost 16 bytes;
97 so just we jump over the first two bytes */
98 ret = ch395_socket_data_send(0, datalen, data);
99 aos_free(data);
100 if (ret) {
101 printf("ch395 lwip low level output len %d fail", datalen);
102 return ERR_IF;
103 }
104
105 return ERR_OK;
106 }
107
108 /**
109 * @brief Should allocate a pbuf and transfer the bytes of the incoming
110 * packet from the interface into the pbuf.
111 *
112 * @param netif the lwip network interface structure for this ethernetif
113 * @return a pbuf filled with the received packet (including MAC header)
114 * NULL on memory error
115 */
low_level_input(struct netif * netif,uint8_t * data,uint32_t datalen)116 static struct pbuf *low_level_input(struct netif *netif, uint8_t *data, uint32_t datalen)
117 {
118 struct pbuf *p = NULL, *q = NULL;
119 uint8_t *buffer = data;
120 uint32_t bufferoffset = 0;
121 uint32_t copylen = 0;
122 uint32_t leftlen = datalen;
123 uint32_t first_copy = 0;
124 uint32_t pbuf_len = 0;
125 void *dest_buf = NULL;
126
127 /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
128 p = pbuf_alloc(PBUF_RAW, datalen + ETH_PAD_SIZE, PBUF_POOL);
129 if (NULL == p) {
130 return NULL;
131 }
132
133 for (q = p; q != NULL; q = q->next) {
134 dest_buf = q->payload;
135 pbuf_len = q->len;
136
137 if (first_copy == 0) {
138 dest_buf = (char *)dest_buf + ETH_PAD_SIZE;
139 pbuf_len = pbuf_len - ETH_PAD_SIZE;
140 first_copy = 1;
141 }
142
143 if (q->len > leftlen) {
144 copylen = leftlen;
145 } else {
146 copylen = pbuf_len;
147 }
148
149 memcpy(dest_buf, &buffer[bufferoffset], copylen);
150 bufferoffset = bufferoffset + copylen;
151 leftlen = leftlen - copylen;
152 }
153
154 return p;
155 }
156
ethernetif_input(void const * argument)157 static void ethernetif_input(void const *argument)
158 {
159 struct pbuf *p;
160 int ret = 0;
161 uint8_t sock = 0;
162 uint16_t recv_len = 0;
163 uint8_t *precv_data = NULL;
164 struct netif *netif = (struct netif *)argument;
165
166 /* then we need to recv the data */
167 precv_data = aos_malloc(CH395_MAX_DATA_SIZE);
168 if (NULL == precv_data) {
169 LOGE(TAG, "Fail to malloc %d ", recv_len);
170 return;
171 }
172
173 while (1) {
174 ret = aos_sem_wait(&gst_ch395_recv_sem, AOS_WAIT_FOREVER);
175 if (ret) {
176 LOGE(TAG, "Fail to wait socket %d recv sem4 ", sock);
177 continue;
178 }
179
180 ret = ch395_socket_recv_data_len(sock, &recv_len);
181 if (ret) {
182 LOGE(TAG, "Fail to get sock %d recv length", sock);
183 continue;
184 }
185
186 if (recv_len == 0) {
187 LOGE(TAG, "sock %d no data need to recv ", sock);
188 continue;
189 }
190
191 memset(precv_data, 0, CH395_MAX_DATA_SIZE);
192
193 ret = ch395_socket_recv_data(sock, recv_len, precv_data);
194 if (ret) {
195 LOGE(TAG, "sock %d recv data fail len %d", sock, recv_len);
196 continue;
197 }
198
199 p = low_level_input(netif, precv_data, recv_len);
200 if (p != NULL) {
201 if (netif->input(p, netif) != ERR_OK) {
202 pbuf_free(p);
203 }
204 }
205 }
206
207 /*shoudn't reach here incase memory leak */
208 aos_free(precv_data);
209 }
210
low_level_init(struct netif * netif)211 static int low_level_init(struct netif *netif)
212 {
213 unsigned char macaddress[6] = {0};
214 int ret = 0;
215
216 ret = ch395_get_mac_addr(macaddress);
217 if (ret) {
218 printf("eth fail to get mac addr ret %d \r\n", ret);
219 return -1;
220 }
221
222 /* set netif MAC hardware address length */
223 netif->hwaddr_len = ETH_HWADDR_LEN;
224
225 /* set netif MAC hardware address */
226 netif->hwaddr[0] = macaddress[0];
227 netif->hwaddr[1] = macaddress[1];
228 netif->hwaddr[2] = macaddress[2];
229 netif->hwaddr[3] = macaddress[3];
230 netif->hwaddr[4] = macaddress[4];
231 netif->hwaddr[5] = macaddress[5];
232
233 /* set netif maximum transfer unit */
234 netif->mtu = 1500;
235
236 /* Accept broadcast address and ARP traffic */
237 netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
238
239 ret = aos_sem_new(&gst_ch395_recv_sem, 0);
240 if (ret) {
241 printf("creat to new ch395 lwip send sem4 0x%x\r\n", ret);
242 return -1;
243 }
244
245 ret = aos_task_new_ext(&gst_ch395_input_task, "ch395_input",
246 ethernetif_input, netif, CH395_TASK_SIZE, CH395_TASK_PRIO);
247 if (ret) {
248 printf("fail to start ch395 lwip input task 0x%x\r\n", ret);
249 aos_sem_free(&gst_ch395_recv_sem);
250 return -1;
251 }
252
253 ret = aos_task_new_ext(&gst_ch395_lwip_int_task, "ch395_irq",
254 ch395_lwip_inter_proc, NULL, CH395_TASK_SIZE, CH395_TASK_PRIO - 4);
255 if (ret) {
256 LOGE(TAG, "Fail to start chip interrupt proc task 0x%x", ret);
257 aos_task_delete(&gst_ch395_input_task);
258 aos_sem_free(&gst_ch395_recv_sem);
259 return -1;
260 }
261
262 return 0;
263 }
264
265 /**
266 * @brief Should be called at the beginning of the program to set up the
267 * network interface. It calls the function low_level_init() to do the
268 * actual setup of the hardware.
269 *
270 * This function should be passed as a parameter to netif_add().
271 *
272 * @param netif the lwip network interface structure for this ethernetif
273 * @return ERR_OK if the loopif is initialized
274 * ERR_MEM if private data couldn't be allocated
275 * any other err_t on error
276 */
ethernetif_init(struct netif * netif)277 static err_t ethernetif_init(struct netif *netif)
278 {
279 LWIP_ASSERT("netif != NULL", (netif != NULL));
280
281 #if LWIP_NETIF_HOSTNAME
282 /* Initialize interface hostname */
283 netif->hostname = "haas_aos";
284 #endif /* LWIP_NETIF_HOSTNAME */
285
286 netif->name[0] = IFNAME0;
287 netif->name[1] = IFNAME1;
288 /* set netif maximum transfer unit */
289 netif->mtu = 1500;
290
291 /* Accept broadcast address and ARP traffic */
292 netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
293 netif->output = etharp_output;
294 netif->linkoutput = low_level_output;
295
296 /* initialize the hardware */
297 if (low_level_init(netif) != 0) {
298 printf("ch395 lwip low level init fail\r\n");
299 return ERR_IF;
300 }
301
302 return ERR_OK;
303 }
304
post_ip_addr(tcpip_ip_info_t ip)305 void post_ip_addr(tcpip_ip_info_t ip)
306 {
307 /* post ip, mask and gateway in dhcp mode */
308 printf("************************************************** \r\n");
309 printf("DHCP Enable \r\n");
310 printf("ip = %s \r\n", ip4addr_ntoa(ð_ip_info.ip));
311 printf("mask = %s \r\n", ip4addr_ntoa(ð_ip_info.netmask));
312 printf("gateway = %s \r\n", ip4addr_ntoa(ð_ip_info.gw));
313 printf("************************************************** \r\n");
314 }
315
tcpip_dhcpc_cb(struct netif * pstnetif)316 static void tcpip_dhcpc_cb(struct netif *pstnetif)
317 {
318 uint8_t ip_addr[4] = {0};
319 uint8_t mask_addr[4] = {0};
320 uint8_t gw_addr[4] = {0};
321 int32_t ret = 0;
322
323 if (!ip4_addr_cmp(ip_2_ip4(&pstnetif->ip_addr), IP4_ADDR_ANY4)) {
324 // check whether IP is changed
325 if (!ip4_addr_cmp(ip_2_ip4(&pstnetif->ip_addr), ð_ip_info.ip) ||
326 !ip4_addr_cmp(ip_2_ip4(&pstnetif->netmask), ð_ip_info.netmask) ||
327 !ip4_addr_cmp(ip_2_ip4(&pstnetif->gw), ð_ip_info.gw)) {
328 ip4_addr_set(ð_ip_info.ip, ip_2_ip4(&pstnetif->ip_addr));
329 ip4_addr_set(ð_ip_info.netmask, ip_2_ip4(&pstnetif->netmask));
330 ip4_addr_set(ð_ip_info.gw, ip_2_ip4(&pstnetif->gw));
331
332 /* post the dhcp ip address */
333 post_ip_addr(eth_ip_info);
334 /*set ip addr for ch395*/
335 memcpy(ip_addr, ð_ip_info.ip.addr, sizeof(ip_addr));
336 memcpy(mask_addr, ð_ip_info.netmask.addr, sizeof(ip_addr));
337 memcpy(gw_addr, ð_ip_info.gw.addr, sizeof(ip_addr));
338 printf("\r\nip: %d:%d:%d:%d mask: %d:%d:%d:%d gw:%d:%d:%d:%d \r\n",
339 ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3],
340 mask_addr[0], mask_addr[1], mask_addr[2], mask_addr[3],
341 gw_addr[0], gw_addr[1], gw_addr[2], gw_addr[3]);
342 ret = ch395_set_ip_addr(ip_addr);
343 if (ret) {
344 printf("set ip addr fail \r\n");
345 }
346 ret = ch395_set_gw_ip_addr(gw_addr);
347 if (ret) {
348 printf("set gateway ip addr fail \r\n");
349 }
350 ch395_set_ip_mask_addr(mask_addr);
351 if (ret) {
352 printf("set ip mask addr fail \r\n");
353 }
354 }
355 event_publish(EVENT_NETMGR_DHCP_SUCCESS, NULL);
356 }
357
358 return;
359 }
360
tcpip_dhcpc_start(struct netif * pstnetif)361 err_t tcpip_dhcpc_start(struct netif *pstnetif)
362 {
363 int ret = 0;
364 /*at first try to enable dhcp*/
365 if (NULL == pstnetif) {
366 printf("input netif is NULL \r\n");
367 return -1;
368 }
369
370 if (netif_is_up(pstnetif)) {
371 if (dhcp_start(pstnetif) != ERR_OK) {
372 LOG("dhcp client start failed");
373 return -1;
374 }
375 }
376
377 netif_set_status_callback(pstnetif, tcpip_dhcpc_cb);
378 return 0;
379 }
380
tcpip_init_done(void * arg)381 static void tcpip_init_done(void *arg)
382 {
383 #if LWIP_IPV4
384 ip4_addr_t ipaddr, netmask, gw;
385 memset(&ipaddr, 0, sizeof(ipaddr));
386 memset(&netmask, 0, sizeof(netmask));
387 memset(&gw, 0, sizeof(gw));
388 netif_add(ð_lwip_netif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, tcpip_input);
389 #endif
390
391 netif_set_default(ð_lwip_netif);
392 netif_set_up(ð_lwip_netif);
393 }
394
395 /* should be called after dhcp is done */
ch395_eth_sock_macraw(void)396 static int ch395_eth_sock_macraw(void)
397 {
398 int ret = 0;
399
400 ret = ch395_set_sock_proto_type(0, PROTO_TYPE_MAC_RAW);
401 if (ret) {
402 LOGE(TAG, "Fail to set sock 0 macraw mode fail");
403 return -1;
404 }
405
406 ret = ch395_socket_open(0);
407 if (ret) {
408 LOGE(TAG, "ch395 lwip fail to open socket 0 macraw mode");
409 return -1;
410 }
411
412 return 0;
413 }
414
ch395_lwip_sock_interrupt_proc(uint8_t sockindex)415 static void ch395_lwip_sock_interrupt_proc(uint8_t sockindex)
416 {
417 uint8_t sock_int_socket = 0;
418 uint16_t recv_len = 0;
419 uint8_t *precv_data = NULL;
420 int32_t ret = 0;
421
422 /* get sock interrupt status */
423 ret = ch395_get_sock_int_status(sockindex, &sock_int_socket);
424 /* send done proc */
425 if (sock_int_socket & SINT_STAT_SENBUF_FREE) {
426 // LOGI(TAG, "sock %d send data done ", sockindex);
427 /*it means send ok */
428 }
429
430 if (sock_int_socket & SINT_STAT_SEND_OK) {
431 /*only one buf is ok, so do nothing for now*/
432 }
433
434 if (sock_int_socket & SINT_STAT_CONNECT) {
435 /*the interrup only happened in tcp mode , in socket 0
436 macraw mode nothing todo */
437 }
438
439 if (sock_int_socket & SINT_STAT_DISCONNECT) {
440 /*the interrup only happened in tcp mode , in socket 0
441 macraw mode nothing todo */
442 }
443
444 if (sock_int_socket & SINT_STAT_TIM_OUT) {
445 /*the interrup only happened in tcp mode , in socket 0
446 macraw mode nothing todo */
447 }
448
449 if (sock_int_socket & SINT_STAT_RECV) {
450 // LOGI(TAG, "sock %d recv data ", sockindex);
451 /*get recv data length*/
452 /*signal recv sem4*/
453 if (aos_sem_is_valid(&gst_ch395_recv_sem)) {
454 aos_sem_signal(&gst_ch395_recv_sem);
455 }
456 }
457 }
458
ch395_lwip_inter_proc(void)459 static void ch395_lwip_inter_proc(void)
460 {
461 uint16_t ch395_int_status;
462 uint8_t dhcp_status = 0;
463 uint8_t phy_status = 0;
464 uint32_t retry = 0;
465 int32_t ret = 0;
466 ip4_addr_t ipaddr = {0};
467 ip4_addr_t netmask = {0};
468 ip4_addr_t gw = {0};
469
470 while (1) {
471 /*every 50 ms proc the chip interrupt*/
472 aos_msleep(5);
473
474 ch395_int_status = 0;
475 ret = ch395_get_global_all_int_status(&ch395_int_status);
476
477 if (ch395_int_status & GINT_STAT_UNREACH) {
478 /* nothing to do for now*/
479 LOGI(TAG, "recv unreach interrupt, nothing to do for now");
480 }
481
482 if (ch395_int_status & GINT_STAT_IP_CONFLI) {
483 LOGI(TAG, "recv ip confict interrupt, nothing to do for now");
484 }
485
486 if (ch395_int_status & GINT_STAT_PHY_CHANGE) {
487 /*get phy status*/
488 ret = ch395_get_phy_status(&phy_status);
489 if (ret != 0) {
490 LOGE(TAG, "Fail to get phy status");
491 continue;
492 }
493 gst_lwipch395info.phystate = phy_status;
494 if (phy_status == PHY_DISCONN) {
495 LOGI(TAG, "eth link down");
496 event_publish(EVENT_ETHERNET_LINK_DOWN, NULL);
497 } else {
498 /*start up to dhcp*/
499 LOGI(TAG, "eth link up");
500 event_publish(EVENT_ETHERNET_LINK_UP, ð_lwip_netif);
501 }
502 }
503
504 /* dhcp/pppoe interrup proc */
505 if (ch395_int_status & GINT_STAT_DHCP) {
506 ret = ch395_dhcp_get_status(&dhcp_status);
507 if (ret) {
508 LOGE(TAG, "Fail to dhcp result");
509 continue;
510 }
511
512 if (dhcp_status == 0) {
513 /*try to get ip interface */
514 do {
515 memset(&gst_lwipch395info.ip_info, 0, sizeof(gst_lwipch395info.ip_info));
516 ret = ch395_get_ip_interface(&gst_lwipch395info.ip_info);
517 if (ret) {
518 LOGE(TAG, "Fail to get eth interface ip info");
519 continue;
520 }
521
522 if (gst_lwipch395info.ip_info.ipaddr[0] != 0 && gst_lwipch395info.ip_info.ipaddr[1] != 0) {
523 /* Post got ip event */
524 LOGI(TAG, "get ip info %d.%d.%d.%d gateway %d.%d.%d.%d mask %d.%d.%d.%d dns1 %d.%d.%d.%d dns2 %d.%d.%d.%d\r\n",
525 gst_lwipch395info.ip_info.ipaddr[0], gst_lwipch395info.ip_info.ipaddr[1], gst_lwipch395info.ip_info.ipaddr[2], gst_lwipch395info.ip_info.ipaddr[3],
526 gst_lwipch395info.ip_info.gateway[0], gst_lwipch395info.ip_info.gateway[1], gst_lwipch395info.ip_info.gateway[2], gst_lwipch395info.ip_info.gateway[3],
527 gst_lwipch395info.ip_info.ip_mask[0], gst_lwipch395info.ip_info.ip_mask[1], gst_lwipch395info.ip_info.ip_mask[2], gst_lwipch395info.ip_info.ip_mask[3],
528 gst_lwipch395info.ip_info.ip_dns1[0], gst_lwipch395info.ip_info.ip_dns1[1], gst_lwipch395info.ip_info.ip_dns1[2], gst_lwipch395info.ip_info.ip_dns1[3],
529 gst_lwipch395info.ip_info.ip_dns2[0], gst_lwipch395info.ip_info.ip_dns2[1], gst_lwipch395info.ip_info.ip_dns2[2], gst_lwipch395info.ip_info.ip_dns2[3]);
530 memcpy(&ipaddr.addr, gst_lwipch395info.ip_info.ipaddr, 4);
531 memcpy(&netmask.addr, gst_lwipch395info.ip_info.ip_mask, 4);
532 memcpy(&gw.addr, gst_lwipch395info.ip_info.gateway, 4);
533
534 netif_set_addr(ð_lwip_netif, &ipaddr, &netmask, &gw);
535 tcpip_dhcpc_cb(ð_lwip_netif);
536 break;
537 }
538 aos_msleep(1000);
539 retry++;
540 } while (retry < 10);
541 } else {
542 // LOGD(TAG, "dhcp time out, cannot get ip addr, it will go on dhcp after 16 second");
543 }
544 }
545 if (ch395_int_status & GINT_STAT_SOCK0) {
546 ch395_lwip_sock_interrupt_proc(0);
547 }
548 }
549 }
550
eth_lwip_tcpip_init(void)551 int eth_lwip_tcpip_init(void)
552 {
553 int ret = 0;
554 unsigned char chip_ver = 0;
555 unsigned char soft_ver = 0;
556 spi_dev_t eth_spi_dev = {0};
557
558 eth_spi_dev.port = 0;
559 eth_spi_dev.config.data_size = SPI_DATA_SIZE_8BIT;
560 eth_spi_dev.config.mode = SPI_WORK_MODE_3;
561 eth_spi_dev.config.cs = SPI_CS_DIS;
562 eth_spi_dev.config.freq = 2000000;
563 eth_spi_dev.config.role = SPI_ROLE_MASTER;
564 eth_spi_dev.config.firstbit = SPI_FIRSTBIT_MSB;
565 eth_spi_dev.config.t_mode = SPI_TRANSFER_NORMAL;
566
567 ret = ch395_module_init(ð_spi_dev);
568 if (ret) {
569 printf("spi init fail 0x%x, port %d, spi role %d, firstbit %d, work_mode %d, freq %d",
570 ret, eth_spi_dev.port, eth_spi_dev.config.role, eth_spi_dev.config.firstbit,
571 eth_spi_dev.config.mode, eth_spi_dev.config.freq);
572 return -1;
573 }
574
575 ret = ch395_get_version(&chip_ver, &soft_ver);
576 if (ret || chip_ver != 0x4) {
577 printf("Fail to get chip ver: 0x%x soft ver 0x%x ret : 0x%x", chip_ver, soft_ver, ret);
578 return -1;
579 }
580
581 ret = ch395_set_func_param(SOCK_CTRL_FLAG_SOCKET_CLOSE);
582 if (ret) {
583 printf("eht init fail : ch395 set func param fail %d", ret);
584 return -1;
585 }
586
587 ret = ch395_dev_init();
588 if (ret) {
589 printf("eht init fail : ch395 init fail %d", ret);
590 return -1;
591 }
592
593 ret = ch395_eth_sock_macraw();
594 if (ret) {
595 printf("eth fail to set socket 0 macraw mode \r\n", ret);
596 return -1;
597 }
598
599 ret = ch395_ping_enable(1);
600 if (ret) {
601 printf("eht init fail : ch395 ping enable fail %d", ret);
602 }
603
604 tcpip_init_done(NULL);
605
606 return 0;
607 }
608