Esempio n. 1
0
// Put the following function into your main packet loop.
// returns plen of original packet if buf is not touched.
// returns 0 if plen was originally zero. returns 0 if DHCP messages
// was processed.
// We don't need to expect changing IP addresses. We can stick
// to the IP that we got once. The server has really no power to
// do anything about that.
uint16_t packetloop_dhcp_renewhandler(uint8_t *buf,uint16_t plen){
        if (dhcp_6sec_cnt> 8){  // we let it run a bit faster than once every minute because it is better this expires too early than too late
                dhcp_6sec_cnt=0;
                // count down unless the lease was infinite
                if (dhcp_opt_leasetime_minutes < 0xffff && dhcp_opt_leasetime_minutes>1){
                        dhcp_opt_leasetime_minutes--;
                }
        }
        if (plen ==0 && dhcp_opt_leasetime_minutes < 3){
                if (!enc28j60linkup()) return(plen); // do nothing if link is down
                dhcp_tid++;
                send_dhcp_renew_request(buf,dhcp_tid,dhcp_yiaddr);
                dhcp_opt_leasetime_minutes=5; // repeat in two minutes if no answer
                return(0);
        }
        if (plen && is_dhcp_msg_for_me(buf,plen,dhcp_tid)){
                // we check the dhcp_renew_tid because if 
                if (dhcp_get_message_type(buf,plen)==5){ // DHCPACK =5
                        // success, DHCPACK, we have the IP
                        if (dhcp_is_renew_tid(buf,plen)){
                                dhcp_option_parser(buf,plen); // get new lease time, it will as well GW and netmask but those should not change
                        }
                }
                return(0);
        }
        return(plen);
}
Esempio n. 2
0
uint8_t EtherShield::ES_enc28j60linkup(void) {
	return enc28j60linkup();
}
Esempio n. 3
0
// send a DNS udp request packet
// See http://www.ietf.org/rfc/rfc1034.txt 
// and http://www.ietf.org/rfc/rfc1035.txt
// gwmac is the internal mac addess of your router
// because we use 8.8.8.8 as a DNS server
uint8_t dnslkup_request(uint8_t *buf,const char *hostname,const uint8_t *gwmac)
{
        uint8_t i,lenpos,lencnt;
        haveDNSanswer=0;
        if(!enc28j60linkup()){
                dns_ansError=4; // could not send request, link down
                return(1);
        }
        dns_ansError=0;
        dnstid_l++; // increment for next request, finally wrap
        send_udp_prepare(buf,(DNSCLIENT_SRC_PORT_H<<8)|(dnstid_l&0xff),dnsip,53,gwmac);
        // fill tid:
        //buf[UDP_DATA_P] see below
        buf[UDP_DATA_P+1]=dnstid_l;
        buf[UDP_DATA_P+2]=1; // flags, standard recursive query
        i=3;
        // most fields are zero, here we zero everything and fill later
        while(i<12){ 
                buf[UDP_DATA_P+i]=0;
                i++;
        }
        buf[UDP_DATA_P+5]=1; // 1 question
        // the structure of the domain name
        // we ask for is always length, string, length, string, ...
        // for earch portion of the name.
        // www.twitter.com would become: 3www7twitter3com
        // 
        // the first len starts at i=12
        lenpos=12;
        i=13;
        lencnt=1; // need to start with one as there is no dot before the domain name and the below algorithm assumes lencnt=0 at dot
        while(*hostname){
                if (*hostname=='\0') break;
                if (*hostname=='.'){
                        buf[UDP_DATA_P+lenpos]=lencnt-1; // fill the length field
                        lencnt=0;
                        lenpos=i;
                }
                buf[UDP_DATA_P+i]=*hostname;
                lencnt++;
                i++;
                hostname++;
        }
        buf[UDP_DATA_P+lenpos]=lencnt-1;
        buf[UDP_DATA_P+i]=0; // terminate with zero, means root domain.
        i++;
        buf[UDP_DATA_P+i]=0;
        i++;
        buf[UDP_DATA_P+i]=1; // type A
        i++;
        buf[UDP_DATA_P+i]=0; 
        i++;
        buf[UDP_DATA_P+i]=1; // class IN
        i++;
        // we encode the length into the upper byte of the TID
        // this way we can easily jump over the query section
        // of the answer:
        buf[UDP_DATA_P]=i-12;
        send_udp_transmit(buf,i);
        return(0);
}
Esempio n. 4
0
boolean NanodeUIP::link_is_up(void) {
  return enc28j60linkup()!=0;
}
Esempio n. 5
0
void NanodeUIP::wait_for_link(void) {
  while (!enc28j60linkup());
}
Esempio n. 6
0
// Initial_tid can be a random number for every board. E.g the last digit
// of the mac address. It is not so important that the number is random.
// It is more important that it is unique and no other board on the same
// Lan has the same number. This is because there might be a power outage
// and all boards reboot afterwards at the same time. At that moment they
// must all have different TIDs otherwise there will be an IP address mess-up.
//
// The function returns 1 once we have a valid IP. 
// At this point you must not call the function again.
uint8_t packetloop_dhcp_initial_ip_assignment(uint8_t *buf,uint16_t plen,uint8_t initial_tid){
        static uint16_t init=0x5fff; // about 2 sec delay
        uint8_t cmd;
        // do nothing if the link is down
        if (!enc28j60linkup()) return(0);
        // first time that this function is called:
        if (plen==0){
                if (init==2){
                        init=1;
                        dhcp_6sec_cnt=0;
                        dhcp_tid=initial_tid;
                        // Reception of broadcast packets is turned off by default, but
                        // the DHCP offer message that the DHCP server sends will be
                        // a broadcast packet. Enable here and disable later.
                        enc28j60EnableBroadcast();
                        send_dhcp_discover(buf,dhcp_tid);
                        return(0);
                }
                if (dhcp_yiaddr[0]==0 && dhcp_6sec_cnt > 5){
                        // still no IP after 30 sec
                        dhcp_tid++;
                        dhcp_6sec_cnt=0;
                        // Reception of broadcast packets is turned off by default, but
                        // the DHCP offer message that the DHCP server sends will be
                        // a broadcast packet. Enable here and disable later.
                        enc28j60EnableBroadcast();
                        send_dhcp_discover(buf,dhcp_tid);
                        return(0);
                }
                // We have a little delay (about 2sec) at startup. Sometimes
                // the power fluctuates or the programmer causes
                // the board to reset and then immediately reset again.
                // We wait with the sending of a send_dhcp_discover just in case
                // we did already so at the last reset which was possibly less
                // than a second ago.
                if (init>2){
                        init--;
                }
                return(0);
        }
        // plen > 0
        if (is_dhcp_msg_for_me(buf,plen,dhcp_tid)){
                // It's really a borderline case that we the the dhcp_is_renew_tid
                // function call for. It could only happen if the board is power cyceled 
                // during operation.
                if (dhcp_is_renew_tid(buf,plen)==1) return(0); // should have been initial tid, just return
                cmd=dhcp_get_message_type(buf,plen);
                if (cmd==2){ // DHCPOFFER =2
                        init=1; // no more init needed
                        dhcp_get_yiaddr(buf,plen);
                        dhcp_option_parser(buf,plen);
                        // answer offer with a request:
                        send_dhcp_request(buf,dhcp_tid);
                }
                if (cmd==5){ // DHCPACK =5
                        // success, DHCPACK, we have the IP
                        init=1; // no more init needed
                        enc28j60DisableBroadcast();
                        return(1);
                }
        }
        return(0);
}
Esempio n. 7
0
int main(void) {
	static uint8_t buffer[BufferSize + 1];
	int8_t   i;
	uint8_t  message[4] = { 0, 0, CID, P2CID };
	uint16_t received;
	snesIO   port0 = 0xffff, port1 = 0xffff;


	// Initialise basic I/O.
	initLed();
	initInput();
	initOutput();


	// Switched mode: B + Y.
	port0 = recvInput();
	if (port0 == 0xfffc) {
		switchedMode = Enabled;
		ledSignal(5);
	}
	ledOnRed();


	// Initialise network interface.
	enc28j60Init(mymac);
	_delay_ms(100);
	// Magjack leds configuration, see enc28j60 datasheet, page 11
	// LEDB=yellow LEDA=green
	// 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit
	// enc28j60PhyWrite(PHLCON,0b0000 0100 0111 01 10);
	enc28j60PhyWrite(PHLCON, 0x476);
	_delay_ms(100);


	// Get the initial IP via DHCP and configure network.
	init_mac(mymac);
	while (i != 1) {
		received = enc28j60PacketReceive(BufferSize, buffer);
		buffer[BufferSize] = '\0';
		i = packetloop_dhcp_initial_ip_assignment(buffer, received, mymac[5]);
	}
	dhcp_get_my_ip(myip, netmask, gwip);
	client_ifconfig(myip, netmask);


	// Resolve MAC address from server IP.
	if (route_via_gw(serverip)) // Must be routed via gateway.
		get_mac_with_arp(gwip, TransNumGwmac, &arpresolverResultCallback);
	else                        // Server is on local network.
		get_mac_with_arp(serverip, TransNumGwmac, &arpresolverResultCallback);

	while (get_mac_with_arp_wait()) {
		received = enc28j60PacketReceive(BufferSize, buffer);
		// Call packetloop to process ARP reply.
		packetloop_arp_icmp_tcp(buffer, received);
	}


	// Lookup DNS of the server hostname.
	while (dnslkup_haveanswer() != 1) {
		uint16_t tmp;
		received = enc28j60PacketReceive(BufferSize, buffer);
		tmp      = packetloop_arp_icmp_tcp(buffer, received);

		if (received == 0) {
			if (!enc28j60linkup()) continue;
			dnslkup_request(buffer, ServerVHost, gwmac);
			_delay_ms(100);
			continue;
		}

		if (tmp == 0)
			udp_client_check_for_dns_answer(buffer, received);
	}
	dnslkup_get_ip(serverip);


	ledOnGreen(); // Connected.


	while (1) { // Main loop start.
		received = enc28j60PacketReceive(BufferSize, buffer);


		// Software reset: L + R + Select + Start.
		if (port0 == 0xf3f3) reset();


		// Do something while no packet in queue.
		if (received == 0) {
			port0 = recvInput();

			// Prepare message and send it to the server.
			for (i = 0; i < 8; i++) { // Lo-Byte.
				char *c = message;

				*c = port0 & (1 << i)
					? *c |  (1 << i)
					: *c & ~(1 << i);
			}

			for (i = 0; i < 8; i++) { // Hi-Byte.
				char *c = message + 1;

				*c = port0 & (1 << i + 8)
					? *c |  (1 << i)
					: *c & ~(1 << i);
			}

			send_udp(buffer, message, sizeof(message), 57351, serverip, 57350, gwmac);


			// Send controller data to SNES.
			if (switchedMode == Disabled)
				sendOutput(port0, port1);
			else
				sendOutput(port1, port0);

			continue;
		}


		// Answer to ARP requests.
		if (eth_type_is_arp_and_my_ip(buffer, received)) {
			make_arp_answer_from_request(buffer, received);
			continue;
		}


		// Check if IP packets (ICMP or UDP) are for us.
		if (eth_type_is_ip_and_my_ip(buffer, received) == 0)
			continue;


		// Answer ping with pong.
		if (
			buffer[IP_PROTO_P]  == IP_PROTO_ICMP_V &&
			buffer[ICMP_TYPE_P] == ICMP_TYPE_ECHOREQUEST_V) {

			make_echo_reply_from_request(buffer, received);
			continue;
		}


		// Listen for UDP packets on port 57351 (0xe007) and process
		// received data.
		if (
			buffer[IP_PROTO_P]       == IP_PROTO_UDP_V &&
			buffer[UDP_DST_PORT_H_P] == 0xe0 &&
			buffer[UDP_DST_PORT_L_P] == 0x07) {

			for (i = 0; i < 8; i++) {
				uint16_t *c = &port1;

				*c = buffer[UDP_DATA_P] & (1 << i)
					? *c |  (1 << i)
					: *c & ~(1 << i);
			}

			for (i = 0; i < 8; i++) {
				uint16_t *c = &port1;

				*c = buffer[UDP_DATA_P + 1] & (1 << i)
					? *c |  (1 << i + 8)
					: *c & ~(1 << i + 8);
			}
		}
	} // Main loop end.


	return (0);
}
Esempio n. 8
0
/*---------------------------------------------------------------------------*/
int main(void)
{   
    uint16_t rval;     

    /* init hardware layer */
    init_hci();
    timer1_init();
    init_serial();    
    sei();

    led1_high();
    led2_high();

    /* init protothreads */
    PT_INIT(&blink_pt);    
    PT_INIT(&nrf24_pt);
    PT_INIT(&www_client_pt);
    PT_INIT(&www_server_pt);
    PT_INIT(&udp_server_pt);
    PT_INIT(&coap_server_pt);    
    PT_INIT(&temperature_pt);
    PT_INIT(&udp_broadcast_pt);

    /* greeting message */
    dbg(PSTR("> Hello World!\r\n"));   

    /* init the ethernet chip */
    enc28j60Init(mymac);        
    enc28j60PhyWrite(PHLCON,0x476);
    
    /* get automatic IP */
    rval=0;
    init_mac(mymac);        
    while(rval==0)
    {
        plen=enc28j60PacketReceive(BUFFER_SIZE, buf);
        rval=packetloop_dhcp_initial_ip_assignment(buf,plen,mymac[5]);
    }
    dhcp_get_my_ip(myip,netmask,gwip); 
    client_ifconfig(myip,netmask);
    
    /* learn the MAC address of the gateway */
    get_mac_with_arp(gwip,0,&arpresolver_result_callback);
    while(get_mac_with_arp_wait())
    {        
        plen=enc28j60PacketReceive(BUFFER_SIZE, buf);
        packetloop_arp_icmp_tcp(buf,plen);
    }
    
    /* set WWW server port */
    www_server_port(MYWWWPORT);        
    
    dbg(PSTR("> System is ready.\r\n"));   

    led1_low();
    led2_low();

    /* main loop */
    while(1)
    {    
        if(enc28j60linkup())
        {            
            /* poll hardware ethernet buffer */
            plen = enc28j60PacketReceive(BUFFER_SIZE,buf);     
            
            /* terminate the buffer */
            buf[BUFFER_SIZE]='\0';

            /* handle DHCP messages if neccessary */
            plen = packetloop_dhcp_renewhandler(buf,plen);

            /* handle and analyse the packet slightly */
            dat_p = packetloop_arp_icmp_tcp(buf,plen);

            if( dat_p == 0)
            {
                udp_client_check_for_dns_answer(buf,plen);
            } 

            new_packet = 0xFF;
            
            PT_SCHEDULE(blink_thread(&blink_pt));      
            PT_SCHEDULE(nrf24_thread(&nrf24_pt));                  
            PT_SCHEDULE(www_server_thread(&www_server_pt));
            PT_SCHEDULE(udp_server_thread(&udp_server_pt));
            PT_SCHEDULE(www_client_thread(&www_client_pt));
            PT_SCHEDULE(coap_server_thread(&coap_server_pt));
            PT_SCHEDULE(temperature_thread(&temperature_pt));
            PT_SCHEDULE(udp_broadcast_thread(&udp_broadcast_pt));
        }
    }    
    return 0;
}