/*
 * uip-app.c
 *
 *  Created on: Jan 29, 2012
 *      Author: RomanM
 */

#include <string.h>
#include "../port/network-device.h"
#include "../uip.h"
#include "../uip_arp.h"
#include "../timer.h"

#include "uip-app.h"
#include "http/http.h"
#include "echo/echo.h"
#include "rfid/rfid.h"

extern u8_t uip_buf[UIP_BUFSIZE + 2];
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])

struct timer periodic_timer, arp_timer;

/*
 * Initialization of uIP application
 */
void uip_app_init(void) {
	clock_init();			// Clock initialization
	network_device_init();	// Ethernet device initialization

	// Timers initializtion
	timer_set(&periodic_timer, CLOCK_SECOND / 2);
	timer_set(&arp_timer, CLOCK_SECOND * 10);

	// Application initialization
	uip_init();
	uip_http_init();
	uip_echo_init();
}

/*
 * Get IP address
 */
void uip_app_get_ip(uint8_t *ip) {
	memcpy(ip, &uip_hostaddr, sizeof(uip_ipaddr_t));
}

/*
 * Get MAC address
 */
void uip_app_get_mac(uint8_t *mac) {
	memcpy(mac, &uip_ethaddr, sizeof(struct uip_eth_addr));
}

/*
 * Get network device linked status
 */
uint8_t uip_app_linked(void) {
	return network_device_linked();
}

/*
 * uIP main loop
 */
void uip_app_loop(void) {
	uint16_t i;

	uip_len = network_device_read();
	if(uip_len > 0) {
		if(BUF->type == htons(UIP_ETHTYPE_IP)) {
			uip_arp_ipin();
			uip_input();
			if(uip_len > 0) {
				uip_arp_out();
				network_device_send();
			}
		} else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {
			uip_arp_arpin();
			if(uip_len > 0) {
				network_device_send();
			}
		}
	} else if(timer_expired(&periodic_timer)) {
		timer_reset(&periodic_timer);
		for(i = 0; i < UIP_CONNS; i++) {
			uip_periodic(i);
			if(uip_len > 0) {
				uip_arp_out();
				network_device_send();
			}
		}

#if UIP_UDP
		for(i = 0; i < UIP_UDP_CONNS; i++) {
			uip_udp_periodic(i);
			if(uip_len > 0) {
				uip_arp_out();
				network_device_send();
			}
		}
#endif /* UIP_UDP */

		if(timer_expired(&arp_timer)) {
			timer_reset(&arp_timer);
			uip_arp_timer();
		}
	}
}

/*
 * TPC call
 */
void uip_app_call(void) {
	switch (uip_conn->lport) {
		case HTONS(HTTP_PORT):
			uip_http_call();
			break;
		case HTONS(ECHO_PORT):
			uip_echo_call();
			break;
	}
	if (uip_conn->rport == HTONS(RFID_REQUEST_PORT)) {
		uip_rfid_call();
	}
}

/*
 * UDP call
 */
#if UIP_UDP
void uip_udp_app_call(void) {
}
#endif /* UIP_UDP */
