You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					299 lines
				
				8.5 KiB
			
		
		
			
		
	
	
					299 lines
				
				8.5 KiB
			|   
											8 years ago
										 | /*
 | ||
|  |              LUFA Library | ||
|  |      Copyright (C) Dean Camera, 2017. | ||
|  | 
 | ||
|  |   dean [at] fourwalledcubicle [dot] com | ||
|  |            www.lufa-lib.org | ||
|  | */ | ||
|  | 
 | ||
|  | /*
 | ||
|  |   Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com) | ||
|  | 
 | ||
|  |   Permission to use, copy, modify, distribute, and sell this | ||
|  |   software and its documentation for any purpose is hereby granted | ||
|  |   without fee, provided that the above copyright notice appear in | ||
|  |   all copies and that both that the copyright notice and this | ||
|  |   permission notice and warranty disclaimer appear in supporting | ||
|  |   documentation, and that the name of the author not be used in | ||
|  |   advertising or publicity pertaining to distribution of the | ||
|  |   software without specific, written prior permission. | ||
|  | 
 | ||
|  |   The author disclaims all warranties with regard to this | ||
|  |   software, including all implied warranties of merchantability | ||
|  |   and fitness.  In no event shall the author be liable for any | ||
|  |   special, indirect or consequential damages or any damages | ||
|  |   whatsoever resulting from loss of use, data or profits, whether | ||
|  |   in an action of contract, negligence or other tortious action, | ||
|  |   arising out of or in connection with the use or performance of | ||
|  |   this software. | ||
|  | */ | ||
|  | 
 | ||
|  | /** \file
 | ||
|  |  * | ||
|  |  *  uIP Management functions. This file contains the functions and globals needed to maintain the uIP | ||
|  |  *  stack once an RNDIS device has been attached to the system. | ||
|  |  */ | ||
|  | 
 | ||
|  | #define  INCLUDE_FROM_UIPMANAGEMENT_C
 | ||
|  | #include "uIPManagement.h"
 | ||
|  | 
 | ||
|  | /** Connection timer, to retain the time elapsed since the last time the uIP connections were managed. */ | ||
|  | static struct timer ConnectionTimer; | ||
|  | 
 | ||
|  | /** ARP timer, to retain the time elapsed since the ARP cache was last updated. */ | ||
|  | static struct timer ARPTimer; | ||
|  | 
 | ||
|  | /** MAC address of the RNDIS device, when enumerated. */ | ||
|  | struct uip_eth_addr MACAddress; | ||
|  | 
 | ||
|  | 
 | ||
|  | /** Configures the uIP stack ready for network traffic processing. */ | ||
|  | void uIPManagement_Init(void) | ||
|  | { | ||
|  | 	/* uIP Timing Initialization */ | ||
|  | 	clock_init(); | ||
|  | 	timer_set(&ConnectionTimer, CLOCK_SECOND / 2); | ||
|  | 	timer_set(&ARPTimer, CLOCK_SECOND * 10); | ||
|  | 
 | ||
|  | 	/* uIP Stack Initialization */ | ||
|  | 	uip_init(); | ||
|  | 	uip_arp_init(); | ||
|  | 
 | ||
|  | 	/* DHCP/Server IP Settings Initialization */ | ||
|  | 	if (USB_CurrentMode == USB_MODE_Device) | ||
|  | 	{ | ||
|  | 		MACAddress.addr[0] = SERVER_MAC_ADDRESS[0]; | ||
|  | 		MACAddress.addr[1] = SERVER_MAC_ADDRESS[1]; | ||
|  | 		MACAddress.addr[2] = SERVER_MAC_ADDRESS[2]; | ||
|  | 		MACAddress.addr[3] = SERVER_MAC_ADDRESS[3]; | ||
|  | 		MACAddress.addr[4] = SERVER_MAC_ADDRESS[4]; | ||
|  | 		MACAddress.addr[5] = SERVER_MAC_ADDRESS[5]; | ||
|  | 
 | ||
|  | 		#if defined(ENABLE_DHCP_SERVER)
 | ||
|  | 		DHCPServerApp_Init(); | ||
|  | 		#endif
 | ||
|  | 
 | ||
|  | 		uip_ipaddr_t IPAddress, Netmask, GatewayIPAddress; | ||
|  | 		uip_ipaddr(&IPAddress,        DEVICE_IP_ADDRESS[0], DEVICE_IP_ADDRESS[1], DEVICE_IP_ADDRESS[2], DEVICE_IP_ADDRESS[3]); | ||
|  | 		uip_ipaddr(&Netmask,          DEVICE_NETMASK[0],    DEVICE_NETMASK[1],    DEVICE_NETMASK[2],    DEVICE_NETMASK[3]); | ||
|  | 		uip_ipaddr(&GatewayIPAddress, DEVICE_GATEWAY[0],    DEVICE_GATEWAY[1],    DEVICE_GATEWAY[2],    DEVICE_GATEWAY[3]); | ||
|  | 		uip_sethostaddr(&IPAddress); | ||
|  | 		uip_setnetmask(&Netmask); | ||
|  | 		uip_setdraddr(&GatewayIPAddress); | ||
|  | 	} | ||
|  | 	else | ||
|  | 	{ | ||
|  | 		#if defined(ENABLE_DHCP_CLIENT)
 | ||
|  | 		DHCPClientApp_Init(); | ||
|  | 		#else
 | ||
|  | 		uip_ipaddr_t IPAddress, Netmask, GatewayIPAddress; | ||
|  | 		uip_ipaddr(&IPAddress,        DEVICE_IP_ADDRESS[0], DEVICE_IP_ADDRESS[1], DEVICE_IP_ADDRESS[2], DEVICE_IP_ADDRESS[3]); | ||
|  | 		uip_ipaddr(&Netmask,          DEVICE_NETMASK[0],    DEVICE_NETMASK[1],    DEVICE_NETMASK[2],    DEVICE_NETMASK[3]); | ||
|  | 		uip_ipaddr(&GatewayIPAddress, DEVICE_GATEWAY[0],    DEVICE_GATEWAY[1],    DEVICE_GATEWAY[2],    DEVICE_GATEWAY[3]); | ||
|  | 		uip_sethostaddr(&IPAddress); | ||
|  | 		uip_setnetmask(&Netmask); | ||
|  | 		uip_setdraddr(&GatewayIPAddress); | ||
|  | 		#endif
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/* Virtual Webserver Ethernet Address Configuration */ | ||
|  | 	uip_setethaddr(MACAddress); | ||
|  | 
 | ||
|  | 	/* HTTP Webserver Initialization */ | ||
|  | 	HTTPServerApp_Init(); | ||
|  | 
 | ||
|  | 	/* TELNET Server Initialization */ | ||
|  | 	#if defined(ENABLE_TELNET_SERVER)
 | ||
|  | 	TELNETServerApp_Init(); | ||
|  | 	#endif
 | ||
|  | } | ||
|  | 
 | ||
|  | /** uIP Management function. This function manages the uIP stack when called while an RNDIS device has been
 | ||
|  |  *  attached to the system. | ||
|  |  */ | ||
|  | void uIPManagement_ManageNetwork(void) | ||
|  | { | ||
|  | 	if (((USB_CurrentMode == USB_MODE_Host)   && (USB_HostState   == HOST_STATE_Configured)) || | ||
|  | 	    ((USB_CurrentMode == USB_MODE_Device) && (USB_DeviceState == DEVICE_STATE_Configured))) | ||
|  | 	{ | ||
|  | 		uIPManagement_ProcessIncomingPacket(); | ||
|  | 		uIPManagement_ManageConnections(); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | /** uIP TCP/IP network stack callback function for the processing of a given TCP connection. This routine dispatches
 | ||
|  |  *  to the appropriate TCP protocol application based on the connection's listen port number. | ||
|  |  */ | ||
|  | void uIPManagement_TCPCallback(void) | ||
|  | { | ||
|  | 	/* Call the correct TCP application based on the port number the connection is listening on */ | ||
|  | 	switch (uip_conn->lport) | ||
|  | 	{ | ||
|  | 		case HTONS(HTTP_SERVER_PORT): | ||
|  | 			HTTPServerApp_Callback(); | ||
|  | 			break; | ||
|  | 		#if defined(ENABLE_TELNET_SERVER)
 | ||
|  | 		case HTONS(TELNET_SERVER_PORT): | ||
|  | 			TELNETServerApp_Callback(); | ||
|  | 			break; | ||
|  | 		#endif
 | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | /** uIP TCP/IP network stack callback function for the processing of a given UDP connection. This routine dispatches
 | ||
|  |  *  to the appropriate UDP protocol application based on the connection's listen port number. | ||
|  |  */ | ||
|  | void uIPManagement_UDPCallback(void) | ||
|  | { | ||
|  | 	/* Call the correct UDP application based on the port number the connection is listening on */ | ||
|  | 	switch (uip_udp_conn->lport) | ||
|  | 	{ | ||
|  | 		#if defined(ENABLE_DHCP_CLIENT)
 | ||
|  | 		case HTONS(DHCP_CLIENT_PORT): | ||
|  | 			DHCPClientApp_Callback(); | ||
|  | 			break; | ||
|  | 		#endif
 | ||
|  | 		#if defined(ENABLE_DHCP_SERVER)
 | ||
|  | 		case HTONS(DHCP_SERVER_PORT): | ||
|  | 			DHCPServerApp_Callback(); | ||
|  | 			break; | ||
|  | 		#endif
 | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | /** Processes Incoming packets to the server from the connected RNDIS device, creating responses as needed. */ | ||
|  | static void uIPManagement_ProcessIncomingPacket(void) | ||
|  | { | ||
|  | 	/* Determine which USB mode the system is currently initialized in */ | ||
|  | 	if (USB_CurrentMode == USB_MODE_Device) | ||
|  | 	{ | ||
|  | 		/* If no packet received, exit processing routine */ | ||
|  | 		if (!(RNDIS_Device_IsPacketReceived(&Ethernet_RNDIS_Interface_Device))) | ||
|  | 		  return; | ||
|  | 
 | ||
|  | 		LEDs_SetAllLEDs(LEDMASK_USB_BUSY); | ||
|  | 
 | ||
|  | 		/* Read the Incoming packet straight into the UIP packet buffer */ | ||
|  | 		RNDIS_Device_ReadPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, &uip_len); | ||
|  | 	} | ||
|  | 	else | ||
|  | 	{ | ||
|  | 		/* If no packet received, exit processing routine */ | ||
|  | 		if (!(RNDIS_Host_IsPacketReceived(&Ethernet_RNDIS_Interface_Host))) | ||
|  | 		  return; | ||
|  | 
 | ||
|  | 		LEDs_SetAllLEDs(LEDMASK_USB_BUSY); | ||
|  | 
 | ||
|  | 		/* Read the Incoming packet straight into the UIP packet buffer */ | ||
|  | 		RNDIS_Host_ReadPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, &uip_len); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/* If the packet contains an Ethernet frame, process it */ | ||
|  | 	if (uip_len > 0) | ||
|  | 	{ | ||
|  | 		switch (((struct uip_eth_hdr*)uip_buf)->type) | ||
|  | 		{ | ||
|  | 			case HTONS(UIP_ETHTYPE_IP): | ||
|  | 				/* Filter packet by MAC destination */ | ||
|  | 				uip_arp_ipin(); | ||
|  | 
 | ||
|  | 				/* Process Incoming packet */ | ||
|  | 				uip_input(); | ||
|  | 
 | ||
|  | 				/* If a response was generated, send it */ | ||
|  | 				if (uip_len > 0) | ||
|  | 				{ | ||
|  | 					/* Add destination MAC to outgoing packet */ | ||
|  | 					uip_arp_out(); | ||
|  | 
 | ||
|  | 					uip_split_output(); | ||
|  | 				} | ||
|  | 
 | ||
|  | 				break; | ||
|  | 			case HTONS(UIP_ETHTYPE_ARP): | ||
|  | 				/* Process ARP packet */ | ||
|  | 				uip_arp_arpin(); | ||
|  | 
 | ||
|  | 				/* If a response was generated, send it */ | ||
|  | 				if (uip_len > 0) | ||
|  | 				  uip_split_output(); | ||
|  | 
 | ||
|  | 				break; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	LEDs_SetAllLEDs(LEDMASK_USB_READY); | ||
|  | } | ||
|  | 
 | ||
|  | /** Manages the currently open network connections, including TCP and (if enabled) UDP. */ | ||
|  | static void uIPManagement_ManageConnections(void) | ||
|  | { | ||
|  | 	/* Poll TCP connections for more data to send back to the host */ | ||
|  | 	for (uint8_t i = 0; i < UIP_CONNS; i++) | ||
|  | 	{ | ||
|  | 		uip_poll_conn(&uip_conns[i]); | ||
|  | 
 | ||
|  | 		/* If a response was generated, send it */ | ||
|  | 		if (uip_len > 0) | ||
|  | 		{ | ||
|  | 			/* Add destination MAC to outgoing packet */ | ||
|  | 			uip_arp_out(); | ||
|  | 
 | ||
|  | 			/* Split and send the outgoing packet */ | ||
|  | 			uip_split_output(); | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/* Manage open connections for timeouts */ | ||
|  | 	if (timer_expired(&ConnectionTimer)) | ||
|  | 	{ | ||
|  | 		timer_reset(&ConnectionTimer); | ||
|  | 
 | ||
|  | 		LEDs_SetAllLEDs(LEDMASK_USB_BUSY); | ||
|  | 
 | ||
|  | 		for (uint8_t i = 0; i < UIP_CONNS; i++) | ||
|  | 		{ | ||
|  | 			/* Run periodic connection management for each TCP connection */ | ||
|  | 			uip_periodic(i); | ||
|  | 
 | ||
|  | 			/* If a response was generated, send it */ | ||
|  | 			if (uip_len > 0) | ||
|  | 			{ | ||
|  | 				/* Add destination MAC to outgoing packet */ | ||
|  | 				uip_arp_out(); | ||
|  | 
 | ||
|  | 				/* Split and send the outgoing packet */ | ||
|  | 				uip_split_output(); | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		#if defined(ENABLE_DHCP_CLIENT)
 | ||
|  | 		for (uint8_t i = 0; i < UIP_UDP_CONNS; i++) | ||
|  | 		{ | ||
|  | 			/* Run periodic connection management for each UDP connection */ | ||
|  | 			uip_udp_periodic(i); | ||
|  | 
 | ||
|  | 			/* If a response was generated, send it */ | ||
|  | 			if (uip_len > 0) | ||
|  | 			{ | ||
|  | 				/* Add destination MAC to outgoing packet */ | ||
|  | 				uip_arp_out(); | ||
|  | 
 | ||
|  | 				/* Split and send the outgoing packet */ | ||
|  | 				uip_split_output(); | ||
|  | 			} | ||
|  | 		} | ||
|  | 		#endif
 | ||
|  | 
 | ||
|  | 		LEDs_SetAllLEDs(LEDMASK_USB_READY); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/* Manage ARP cache refreshing */ | ||
|  | 	if (timer_expired(&ARPTimer)) | ||
|  | 	{ | ||
|  | 		timer_reset(&ARPTimer); | ||
|  | 		uip_arp_timer(); | ||
|  | 	} | ||
|  | } | ||
|  | 
 |