Files
kunlun/import/lwip/ports/netif/netif_uart.c
2024-09-28 14:24:04 +08:00

609 lines
19 KiB
C

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
/* os shim inlcude */
#include "os_utils_api.h"
/* common inlcude */
#include "iot_config_api.h"
#include "iot_ntoh_api.h"
#include "iot_utils_api.h"
#include "iot_uart_api.h"
#include "iot_board_api.h"
#include "iot_uart_eth_api.h"
#include "iot_crc_api.h"
#include "iot_oem_api.h"
/* to resolve conflict with lwip internal definition. fortunately the value
* is the same.
*/
#ifdef ERR_OK
#undef ERR_OK
#endif
/* lwip internal includes */
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/tcpip.h"
#include "lwip/snmp.h"
#include "lwip/dhcp.h"
#include "lwip/etharp.h"
#include "netif/netif_plc.h"
#include "netif/netif_eth.h"
#if IOT_LWIP_NETIF_UART_SUPPORT
/* force open cli uart port for uart_link, set to 1 if the other ports are occupied. */
#define NETIF_UART_PORT_FORCE_CLI 0
#define netif_uart_printf iot_printf
/* global data strcucture for uart network interface */
typedef struct _netif_uart_global {
/* uart network interface descriptor */
struct netif netif;
/* IPv4 configurations */
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gateway;
/* uart port handler */
iot_uart_h uart_link;
uart_eth_state_msg_t netif_plc_state;
} netif_uart_global_t;
static netif_uart_global_t *p_netif_uart = NULL;
#if !IOT_LWIP_UART_OVER_ETH_SUPPORT
static void netif_uart_rpt_to_stack(uint8_t *data, uint16_t len,
uint8_t unicast)
{
struct pbuf *p;
p = pbuf_alloc(PBUF_LINK, len, PBUF_POOL);
if (p != NULL) {
pbuf_take(p, data, len);
pbuf_realloc(p, len);
LINK_STATS_INC(link.recv);
MIB2_STATS_NETIF_ADD(&p_netif_uart->netif, ifinoctets, p->len);
if (unicast) {
MIB2_STATS_NETIF_INC(&p_netif_uart->netif, ifinucastpkts);
} else {
MIB2_STATS_NETIF_INC(&p_netif_uart->netif, ifinnucastpkts);
}
/* deliver to upper stack */
p_netif_uart->netif.input(p, &p_netif_uart->netif);
} else {
/* drop packet */
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
MIB2_STATS_NETIF_INC(&p_netif_uart->netif, ifindiscards);
}
}
#endif
#if (IOT_LWIP_NETIF_PLC_SUPPORT || PLC_SUPPORT_CCO_ROLE)
static err_t netif_uart_send(struct netif *netif, struct pbuf *p)
{
(void)netif;
(void)p;
//IOT_ASSERT(0);
return ERR_OK;
}
static err_t netif_uart_send_ip4(struct netif *netif, struct pbuf *p,
const ip4_addr_t *ipaddr)
{
iot_pkt_t *pkt;
uart_eth_header_t *header;
if (!p_netif_uart->uart_link) {
goto out;
}
if (ip4_addr_isbroadcast(ipaddr, netif) || ip4_addr_ismulticast(ipaddr)) {
goto out;
}
pkt = iot_pkt_alloc(p->tot_len + UART_ETH_PREAMBLE_LEN +
sizeof(*header) + UART_ETH_BACKEND_LEN, IOT_LWIP_MID);
if (pkt) {
/* add preamble code */
os_mem_cpy(iot_pkt_put(pkt, UART_ETH_PREAMBLE_LEN),
UART_ETH_PREAMBLE_CODE, UART_ETH_PREAMBLE_LEN);
/* add header */
header = (uart_eth_header_t *)iot_pkt_tail(pkt);
header->type = UART_ETH_TYPE_P2P;
header->len = p->tot_len;
header->crc = iot_getcrc32_h16((uint8_t *)header, sizeof(*header) - 2);
iot_pkt_put(pkt, sizeof(*header));
/* add data */
while (p) {
os_mem_cpy(iot_pkt_tail(pkt), p->payload, p->len);
iot_pkt_put(pkt, p->len);
MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->len);
p = p->next;
}
/* add backend code */
os_mem_cpy(iot_pkt_tail(pkt), UART_ETH_BACKEND_CODE,
UART_ETH_BACKEND_LEN);
iot_pkt_put(pkt, UART_ETH_BACKEND_LEN);
/* send to uart link */
iot_uart_send(p_netif_uart->uart_link, pkt, NULL);
LINK_STATS_INC(link.xmit);
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
} else {
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
}
out:
return ERR_OK;
}
#else
#define netif_uart_send_ip4 etharp_output
static err_t netif_uart_send(struct netif *netif, struct pbuf *p)
{
iot_pkt_t *pkt;
uart_eth_header_t *header;
if (!p_netif_uart->uart_link) {
goto out;
}
pkt = iot_pkt_alloc(p->tot_len + UART_ETH_PREAMBLE_LEN +
sizeof(*header) + UART_ETH_BACKEND_LEN, IOT_LWIP_MID);
if (pkt) {
/* add preamble code */
os_mem_cpy(iot_pkt_put(pkt, UART_ETH_PREAMBLE_LEN),
UART_ETH_PREAMBLE_CODE, UART_ETH_PREAMBLE_LEN);
/* add header */
header = (uart_eth_header_t *)iot_pkt_tail(pkt);
header->type = UART_ETH_TYPE_P2P;
header->len = p->tot_len;
header->crc = iot_getcrc32_h16((uint8_t *)header, sizeof(*header) - 2);
iot_pkt_put(pkt, sizeof(*header));
/* add data */
while (p) {
os_mem_cpy(iot_pkt_tail(pkt), p->payload, p->len);
iot_pkt_put(pkt, p->len);
MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->len);
p = p->next;
}
/* add backend code */
os_mem_cpy(iot_pkt_tail(pkt), UART_ETH_BACKEND_CODE,
UART_ETH_BACKEND_LEN);
iot_pkt_put(pkt, UART_ETH_BACKEND_LEN);
/* send to uart link */
iot_uart_send(p_netif_uart->uart_link, pkt, NULL);
LINK_STATS_INC(link.xmit);
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
} else {
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
}
out:
return ERR_OK;
}
#endif
static err_t uartif_init(struct netif *netif)
{
uint8_t local_mac[IOT_MAC_ADDR_LEN] = {0x00, 0x01, 0x7f, 0x04, 0x05, 0x06};
netif->name[0] = 'u';
netif->name[1] = 'r';
netif->linkoutput = netif_uart_send;
#if LWIP_IPV4
netif->output = netif_uart_send_ip4;
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
netif->output_ip6 = NULL;
#endif /* LWIP_IPV6 */
netif->mtu = 4096;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_IGMP;
netif->hwaddr_len = IOT_MAC_ADDR_LEN;
iot_oem_get_module_mac(local_mac);
iot_mac_addr_cpy(netif->hwaddr, local_mac);
#if IOT_LWIP_UART_OVER_ETH_SUPPORT
/* initialize dwc eth. */
netif_eth_set_mac_addr(netif->hwaddr);
#endif
#if (!IOT_LWIP_NETIF_PLC_SUPPORT)
netif->flags |= NETIF_FLAG_ETHERNET | NETIF_FLAG_ETHARP;
#endif
iot_cus_printf("[%s][info] netif macaddr[%x:%x:%x:%x:%x:%x]\n", __FUNCTION__,
netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], netif->hwaddr[3],
netif->hwaddr[4], netif->hwaddr[5]);
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 1000000);
return ERR_OK;
}
static void netif_uart_status_callback(struct netif *state_netif)
{
if (netif_is_up(state_netif)) {
#if LWIP_IPV4
netif_uart_printf("%s status_callback==UP, local interface IP is %s\n",
__FUNCTION__, ip4addr_ntoa(netif_ip4_addr(state_netif)));
#else
netif_uart_printf("%s status_callback==UP\n", __FUNCTION__);
#endif
} else {
netif_uart_printf("%s status_callback==DOWN\n", __FUNCTION__);
}
}
static void netif_uart_link_callback(struct netif *state_netif)
{
if (netif_is_link_up(state_netif)) {
netif_uart_printf("%s link_callback==UP\n", __FUNCTION__);
} else {
netif_uart_printf("%s link_callback==DOWN\n", __FUNCTION__);
}
}
#if !IOT_LWIP_UART_OVER_ETH_SUPPORT
static void netif_uart_recv_intern(void *ctx)
{
iot_pkt_t *pkt = ctx;
netif_uart_rpt_to_stack(iot_pkt_data(pkt),
(uint16_t)iot_pkt_data_len(pkt), 1);
iot_pkt_free(pkt);
}
#endif
static void netif_plc_report_uart_state()
{
iot_pkt_t *pkt;
uart_eth_header_t *header;
uart_eth_state_msg_t *msg;
pkt = iot_pkt_alloc(UART_ETH_PREAMBLE_LEN +
sizeof(*header) + sizeof(*msg) + UART_ETH_BACKEND_LEN, IOT_LWIP_MID);
if (pkt) {
/* add preamble code */
os_mem_cpy(iot_pkt_put(pkt, UART_ETH_PREAMBLE_LEN),
UART_ETH_PREAMBLE_CODE, UART_ETH_PREAMBLE_LEN);
/* add header */
header = (uart_eth_header_t *)iot_pkt_tail(pkt);
header->type = UART_ETH_TYPE_STATE;
header->len = sizeof(*msg);
header->crc = iot_getcrc32_h16((uint8_t *)header, sizeof(*header) - 2);
iot_pkt_put(pkt, sizeof(*header));
/* add message */
msg = (uart_eth_state_msg_t *)iot_pkt_tail(pkt);
os_mem_cpy(msg, &(p_netif_uart->netif_plc_state),
sizeof(uart_eth_state_msg_t));
iot_pkt_put(pkt, sizeof(*msg));
/* add backend code */
os_mem_cpy(iot_pkt_tail(pkt), UART_ETH_BACKEND_CODE,
UART_ETH_BACKEND_LEN);
iot_pkt_put(pkt, UART_ETH_BACKEND_LEN);
/* send to uart link */
iot_uart_send(p_netif_uart->uart_link, pkt, NULL);
}
}
static void netif_uart_recv(uint8_t *buffer, uint32_t buffer_len,
bool_t is_full_frame, uint32_t invalid_data_len)
{
iot_pkt_t *pkt;
uart_eth_header_t *header;
struct eth_hdr *ethhdr;
(void)invalid_data_len;
if (is_full_frame) {
/* skip preamble code */
buffer += UART_ETH_PREAMBLE_LEN;
buffer_len -= UART_ETH_PREAMBLE_LEN;
/* get header */
header = (uart_eth_header_t *)buffer;
buffer += sizeof(*header);
buffer_len -= sizeof(*header);
/* validate length field again with backend code removed */
if (header->len > (buffer_len - UART_ETH_BACKEND_LEN))
return;
/* check header crc */
if (iot_getcrc32_h16((uint8_t *)header, sizeof(*header) - 2) !=
header->crc) {
return;
}
switch (header->type) {
case UART_ETH_TYPE_P2P:
{
#if IOT_LWIP_UART_OVER_ETH_SUPPORT
netif_uart_to_eth_send_by_data(buffer, header->len);
#else
/* report ip data to uart interface */
pkt = iot_pkt_alloc(header->len, IOT_LWIP_MID);
os_mem_cpy(iot_pkt_put(pkt, header->len), buffer, header->len);
tcpip_callback_with_block(netif_uart_recv_intern, pkt, 0);
#endif
break;
}
case UART_ETH_TYPE_PLC:
{
/* validate source mac address */
ethhdr = (struct eth_hdr *)buffer;
if (!iot_mac_addr_cmp(ethhdr->src.addr, header->src_addr)) {
break;
}
/* foward ethernet to plc link */
pkt = iot_pkt_alloc(header->len, IOT_LWIP_MID);
os_mem_cpy(iot_pkt_put(pkt, header->len), buffer, header->len);
tcpip_callback_with_block((tcpip_callback_fn)netif_uart_to_plc_send,
pkt, 0);
break;
}
case UART_ETH_TYPE_QUERY_STATE:
{
netif_plc_report_uart_state();
break;
}
default:
break;
}
}
}
void netif_plc_to_uart_send_by_data(uint8_t *data, uint16_t len)
{
iot_pkt_t *pkt;
uart_eth_header_t *header;
if (!p_netif_uart)
return;
pkt = iot_pkt_alloc(len + UART_ETH_PREAMBLE_LEN +
sizeof(*header) + UART_ETH_BACKEND_LEN, IOT_LWIP_MID);
if (pkt) {
/* add preamble code */
os_mem_cpy(iot_pkt_put(pkt, UART_ETH_PREAMBLE_LEN),
UART_ETH_PREAMBLE_CODE, UART_ETH_PREAMBLE_LEN);
/* add header */
header = (uart_eth_header_t *)iot_pkt_tail(pkt);
header->type = UART_ETH_TYPE_PLC;
header->len = len;
header->crc = iot_getcrc32_h16((uint8_t *)header, sizeof(*header) - 2);
iot_pkt_put(pkt, sizeof(*header));
/* add data */
os_mem_cpy(iot_pkt_tail(pkt), data, len);
iot_pkt_put(pkt, len);
/* add backend code */
os_mem_cpy(iot_pkt_tail(pkt), UART_ETH_BACKEND_CODE,
UART_ETH_BACKEND_LEN);
iot_pkt_put(pkt, UART_ETH_BACKEND_LEN);
/* send to uart link */
iot_uart_send(p_netif_uart->uart_link, pkt, NULL);
}
}
void netif_plc_to_uart_send_by_pbuf(struct pbuf *p)
{
iot_pkt_t *pkt;
uart_eth_header_t *header;
if (!p_netif_uart)
return;
pkt = iot_pkt_alloc(p->tot_len + UART_ETH_PREAMBLE_LEN +
sizeof(*header) + UART_ETH_BACKEND_LEN, IOT_LWIP_MID);
if (pkt) {
/* add preamble code */
os_mem_cpy(iot_pkt_put(pkt, UART_ETH_PREAMBLE_LEN),
UART_ETH_PREAMBLE_CODE, UART_ETH_PREAMBLE_LEN);
/* add header */
header = (uart_eth_header_t *)iot_pkt_tail(pkt);
header->type = UART_ETH_TYPE_PLC;
header->len = p->tot_len;
header->crc = iot_getcrc32_h16((uint8_t *)header, sizeof(*header) - 2);
iot_pkt_put(pkt, sizeof(*header));
/* add data */
while (p) {
os_mem_cpy(iot_pkt_tail(pkt), p->payload, p->len);
iot_pkt_put(pkt, p->len);
p = p->next;
}
/* add backend code */
os_mem_cpy(iot_pkt_tail(pkt), UART_ETH_BACKEND_CODE,
UART_ETH_BACKEND_LEN);
iot_pkt_put(pkt, UART_ETH_BACKEND_LEN);
/* send to uart link */
iot_uart_send(p_netif_uart->uart_link, pkt, NULL);
}
}
void netif_plc_to_uart_state_chg(uint8_t ready, ip_addr_t *ip,
ip_addr_t *netmask, ip_addr_t *gateway, uint16_t mtu)
{
if (!p_netif_uart)
return;
p_netif_uart->netif_plc_state.ready = !!ready;
if (ip && netmask && gateway) {
p_netif_uart->netif_plc_state.ip_valid = 1;
p_netif_uart->netif_plc_state.ip = ip_addr_get_ip4_u32(ip);
p_netif_uart->netif_plc_state.netmask = ip_addr_get_ip4_u32(netmask);
p_netif_uart->netif_plc_state.gateway = ip_addr_get_ip4_u32(gateway);
} else {
p_netif_uart->netif_plc_state.ip_valid = 0;
}
p_netif_uart->netif_plc_state.mtu = mtu;
p_netif_uart->netif_plc_state.crc =
iot_getcrc32_h16((uint8_t *)&(p_netif_uart->netif_plc_state),
sizeof(p_netif_uart->netif_plc_state) - 2);
netif_plc_report_uart_state();
}
#if IOT_LWIP_UART_OVER_ETH_SUPPORT
void netif_eth_to_uart_send_by_data(uint8_t * data, uint32_t len)
{
iot_pkt_t *pkt;
uart_eth_header_t *header;
pkt = iot_pkt_alloc(len + UART_ETH_PREAMBLE_LEN +
sizeof(*header) + UART_ETH_BACKEND_LEN, IOT_LWIP_MID);
if (pkt) {
/* add preamble code */
os_mem_cpy(iot_pkt_put(pkt, UART_ETH_PREAMBLE_LEN),
UART_ETH_PREAMBLE_CODE, UART_ETH_PREAMBLE_LEN);
/* add header */
header = (uart_eth_header_t *)iot_pkt_tail(pkt);
header->type = UART_ETH_TYPE_P2P;
header->len = len;
header->crc = iot_getcrc32_h16((uint8_t *)header, sizeof(*header) - 2);
iot_pkt_put(pkt, sizeof(*header));
/* add data */
os_mem_cpy(iot_pkt_tail(pkt), data, len);
iot_pkt_put(pkt, len);
/* add backend code */
os_mem_cpy(iot_pkt_tail(pkt), UART_ETH_BACKEND_CODE,
UART_ETH_BACKEND_LEN);
iot_pkt_put(pkt, UART_ETH_BACKEND_LEN);
/* send to uart link */
iot_uart_send(p_netif_uart->uart_link, pkt, NULL);
}
}
#else
void netif_eth_to_uart_send_by_data(uint8_t * data, uint32_t len)
{
(void)data;
(void)len;
}
#endif
void netif_uart_init()
{
iot_oem_base_cfg_t *cfg;
iot_oem_get_base_cfg(&cfg);
uint32_t module_type = cfg->module_type;
if (module_type != MODULE_TYPE_CCO && !IOT_STA_CONTROL_MODE) {
return;
}
iot_frame_fmt uart_fmt;
if (p_netif_uart)
return;
p_netif_uart = os_mem_malloc(IOT_LWIP_MID, sizeof(*p_netif_uart));
IOT_ASSERT(p_netif_uart);
/* ## + uart_eth_header_t + data + @@ */
os_mem_set(&uart_fmt, 0, sizeof(uart_fmt));
uart_fmt.preamble_codelen = UART_ETH_PREAMBLE_LEN;
os_mem_cpy(uart_fmt.preamble_code, UART_ETH_PREAMBLE_CODE,
UART_ETH_PREAMBLE_LEN);
uart_fmt.backcode_len = UART_ETH_BACKEND_LEN;
os_mem_cpy(uart_fmt.backcode, UART_ETH_BACKEND_CODE,
UART_ETH_BACKEND_LEN);
uart_fmt.datalen_offset = 8;
uart_fmt.datalen_size = 2;
/* set this value to 2 to skip the crc in the header */
uart_fmt.backcode_offset = 2;
uart_fmt.frame_timeout = 10;
#if (NETIF_UART_PORT_FORCE_CLI)
p_netif_uart->uart_link = iot_uart_open(iot_board_get_uart(UART_CLI_PORT),
netif_uart_recv, 2048, &uart_fmt);
#else /* NETIF_UART_PORT_FORCE_CLI */
#if (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_STA)
p_netif_uart->uart_link = iot_uart_open(iot_board_get_uart(UART_METER_PORT),
netif_uart_recv, 2048, &uart_fmt);
#else /* (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_STA) */
p_netif_uart->uart_link = iot_uart_open(iot_board_get_uart(UART_CLI_PORT),
netif_uart_recv, 4096, &uart_fmt);
#endif /* (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_STA) */
#endif /* NETIF_UART_PORT_FORCE_CLI */
IOT_ASSERT(p_netif_uart->uart_link);
os_mem_set(&(p_netif_uart->netif_plc_state), 0,
sizeof(p_netif_uart->netif_plc_state));
p_netif_uart->netif_plc_state.crc =
iot_getcrc32_h16((uint8_t *)&(p_netif_uart->netif_plc_state),
sizeof(p_netif_uart->netif_plc_state) - 2);
/* initialize uart interface IP. as uart is P2P link, so FW will use
* 192.168.0.1 and host will use 192.168.0.2 as fixed IP.
*/
IP_ADDR4(&p_netif_uart->gateway, 0, 0, 0, 0);
IP_ADDR4(&p_netif_uart->ipaddr, 192, 168, 0, 1);
IP_ADDR4(&p_netif_uart->netmask, 255, 255, 255, 0);
netif_add(&p_netif_uart->netif, ip_2_ip4(&p_netif_uart->ipaddr),
ip_2_ip4(&p_netif_uart->netmask), ip_2_ip4(&p_netif_uart->gateway),
NULL, uartif_init, tcpip_input);
netif_set_status_callback(&p_netif_uart->netif, netif_uart_status_callback);
netif_set_link_callback(&p_netif_uart->netif, netif_uart_link_callback);
/* enable interface by default */
netif_set_up(&p_netif_uart->netif);
netif_set_link_up(&p_netif_uart->netif);
}
#else /* IOT_LWIP_NETIF_UART_SUPPORT */
void netif_plc_to_uart_send_by_data(uint8_t *data, uint16_t len)
{
(void)data;
(void)len;
}
void netif_plc_to_uart_send_by_pbuf(struct pbuf *p)
{
(void)p;
}
void netif_plc_to_uart_state_chg(uint8_t ready, ip_addr_t *ip)
{
(void)ready;
(void)ip;
}
void netif_uart_init()
{
}
#endif /* IOT_LWIP_NETIF_UART_SUPPORT */