test code for our MBED board

Dependencies:   mbed lwip

network.c

Committer:
lolpcc
Date:
2011-05-04
Revision:
1:6877bb99aa17

File content as of revision 1:6877bb99aa17:

//#include "TCPCallbackConnection.h"
//#include "NetServer.h"
#include "mbed.h"
#include "led.h"
#include "can.h"
#include "cmd.h"
#include "help_data.h"
#include "SNTPClient.h"
#include "breakup.h"
#include "ticker.h"
#include "useful.h"

#include "lwip/opt.h"
#include "lwip/stats.h"
#include "lwip/sys.h"
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/dns.h"
#include "lwip/dhcp.h"
#include "lwip/init.h"
#include "lwip/netif.h"
#include "netif/etharp.h"
#include "netif/loopif.h"
#include "device.h"

Ethernet ethernet;
extern int net_state;
extern char station_id;
volatile char stage = 0;

struct netif    netif_data;

char *header = "HTTP/1.1 200 OK\r\n"
                        "Content-Type: text/html\r\n"
                        "Connection: Close\r\n\r\n"
                        "<html>\r\n"
                        "<head>\r\n"
                        "<title>%s</title>\r\n"
                        "<style type='text/css'>\r\n"
                        "body{font-family:'Arial, sans-serif', sans-serif;font-size:.8em;background-color:#fff;}\r\n"
                        "</style>\r\n"
                        "</head>\r\n";

char network_write_packet(struct tcp_pcb *pcb, char *buf)
{
    if (tcp_write(pcb, (void *)buf, strlen(buf), 1) == ERR_OK) {
        tcp_output(pcb);
        lprintf("Wrote packet String (Size %d bytes)OK...\n",strlen(buf));
        return(1);
    } else {
        lprintf("Transission Problem (Size %d bytes), Closing connection...\n",strlen(buf));
        tcp_close(pcb);
        return(0);
    }
}
void network_send_page(struct tcp_pcb *pcb,char *head, char *body, char *tail)
{
    if(network_write_packet(pcb, head)){
        if(network_write_packet(pcb, body)){
            if(network_write_packet(pcb, tail)){
                tcp_close(pcb);
            } else {
               tcp_close(pcb);
            }
        } else {
            tcp_close(pcb);
        }
    } else {
        tcp_close(pcb);
    }
}
int network_text_packet(struct tcp_pcb *pcb, char *buf)
{
    char    str[0x1200];    /* So we can take a 1024 byte string max */
    char    c;
    int     a = 0;          /* Input pointer */
    int     b = 0;          /* output pointer */
    
    str[b]='<';
    b++;
    str[b]='p';
    b++;
    str[b]='r';
    b++;
    str[b]='e';
    b++;
    str[b]='>';
    b++;
    
    while(a != strlen(buf)){
        c = buf[a];
        if(c=='\n'){
            str[b]='<';
            b++;
            str[b]='b';
            b++;
            str[b]='r';
            b++;
            str[b]='>';
            b++;
            str[b]='\n';
            b++;
            a++;
        } else if(c=='<') {
            a++;
        } else if(c=='>') {
            a++;
        } else {
            str[b] = c;
            a++;
            b++;
        }
    }
    str[b]='<';
    b++;
    str[b]='/';
    b++;
    str[b]='p';
    b++;
    str[b]='r';
    b++;
    str[b]='e';
    b++;
    str[b]='>';
    b++;
    str[b]='\0';
    if(!network_write_packet(pcb, str)){
        lprintf("Problem Packet is:\n%s",str);
        tcp_close(pcb);
        return(1);
    }
    return(0);
}
err_t recv_callback(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) 
{
    struct netif   *netif = &netif_data;
    char *p1[100];   /* Used for the broke apart GET request */
    char *p2[3];     /* Diagnostics call */
    char *p3[10];    /* Diagnostics data */
    char head[1024],body[1024],tail[200];
    int  ret;
     
    lprintf("TCP callback from %d.%d.%d.%d\n", ip4_addr1(&(pcb->remote_ip)),ip4_addr2(&(pcb->remote_ip)),ip4_addr3(&(pcb->remote_ip)),ip4_addr4(&(pcb->remote_ip)));
    char *data;
    /* Check if status is ok and data is arrived. */
    if (err == ERR_OK && p != NULL) {
        /* Inform TCP that we have taken the data. */
        tcp_recved(pcb, p->tot_len);
        data = static_cast<char *>(p->payload);
        /* If the data is a GET request we can handle it. */
        if (strncmp(data, "GET ", 4) == 0) {
            lprintf("Handling GET request...\r\n");
            lprintf("Request:\r\n%s\r\n", data);
            breakup(data,p1,'/');
            time_t seconds = time(NULL);
            sprintf(tail,"<br><small><A href=\"mailto:pcc@cs.york.ac.uk\">"
                "pcc@cs.york.ac.uk</a>\n\r</small>\n\r"
                "<small>mbed RTC time:%s</small><br/>\n\r"
                "<a href=0>Home</a><br><br>\n\r"
                "</body>\n\r</html>\n\r",ctime(&seconds));
            switch(p1[2][0]){
                case    '0'     :   /* Home Page */
                    sprintf(head,header,"MBED Home");
                    sprintf(body,"<h1>Petes MBED Homepage</h1>\n\r"
                        "<a href=1>Board Type</a><br>\n\r"
                        "<a href=2>Networking</a><br>\n\r"
                        "<a href=3>Commands</a><br>\n\r"
                        "<a href=4>CAN Bus</a><br>\n\r"
                        "<a href=5>Diags</a><br>\n\r");
                    network_send_page(pcb,head,body,tail);
                    break;
                case    '1'     :   /* Do something for page 1 */
                    sprintf(head,header,"Board Type");
                    sprintf(body,"<h1>MBED Board Data</h1>\n\r"
                                "Philips NXP <a href=http://mbed.org/nxp/lpc1768/>LPC1768</a>"
                                " Micro Controler <br>\n\r"
                                "512K Flash Memory, 64K SRAM<br>\n\r"
                                "<h4>MCP Solution gives:-</h4>\n\r"
                                "1 * RS232 channel, 1 * CAN bus channel<br>\n\r"
                                "Audio in and out, plus 4 analog inputs<br>\n\r"
                                "Micro SD card slot, USB + TCPIP networking<br>\n\r"
                                "+ I2C bus and selected I/O<br><br>\n\r"
                                "See mbed.org for data<br>\n\r");
                    network_send_page(pcb,head,body,tail);
                break;
                case    '2'     :   /* Networking */
                    sprintf(head,header,"Network");
                    sprintf(body,     "<h1>MBED Networking</h1>\n\r"
                    "<h2>mbed Network Configuration</h2>\n\r"
                    "mbed HW address: %02x:%02x:%02x:%02x:%02x:%02x<br/>\n\r"
                    "mbed IP Address: %s<br/>\n\r"
                    "Station: %d<br>",
                    (char*) netif->hwaddr[0],
                    (char*) netif->hwaddr[1],
                    (char*) netif->hwaddr[2],
                    (char*) netif->hwaddr[3],
                    (char*) netif->hwaddr[4],
                    (char*) netif->hwaddr[5],
                    inet_ntoa(*(struct in_addr*)&(netif->ip_addr)),
                    station_id
                   );
                    network_send_page(pcb,head,body,tail);
                break;
                case    '3'     :   /* Do something for page 3 */
                    sprintf(head,header,"Commands");
                    network_write_packet(pcb,head);
                    sprintf(body,"<h1>MBED Commands</h1>\n\r");
                    network_write_packet(pcb,body);
                    network_text_packet(pcb,HELP_STRING);
                    network_text_packet(pcb,HELP_STRING2);
                    network_text_packet(pcb,HELP_STRING3);
                    network_write_packet(pcb,tail);
                    tcp_close(pcb);
                break;
                case    '4'     :   /* Do something for page 4 */
                    sprintf(head,header,"CAN Bus<br>");
                    network_send_page(pcb,head,body,tail);
                break;
                case    '5'     :   /* Diagnostics page */
                    sprintf(head,header,"Board Diags");
                    network_write_packet(pcb,head);
                    /* Command handler */
                    if(breakup(p1[2],p2,'?')>1){
                        ret = breakup(p2[1],p3,'&');
                        if((strcmp(p3[0],"ticker"))==0)
                            setup_ticker();
                        else if((strcmp(p3[0],"lcd"))==0)
                            lcd_test(ret,p3);
                        else
                            lprintf("Command not found, Looking for %s\n",p3[0]);
                    }
                    network_write_packet(pcb,"<a href=5?ticker&1>Ticker Start</a><br>\n\r");
                    network_write_packet(pcb,"<a href=5?lcd&1>String to LCD 1</a><br>\n\r");
                    network_write_packet(pcb,"<a href=5?lcd&2>String to LCD 2</a><br>\n\r");
                    network_write_packet(pcb,"<a href=5?sseg>Seven Segment driver test</a><br>\n\r");
                    network_write_packet(pcb,tail);
                    tcp_close(pcb);
                    
                break;
                default         :
                    sprintf(head,header,"MBED Board");
                    sprintf(body,"<h1>404 Error</h1>\n\r");
                    network_send_page(pcb,head,body,tail);
                break;
            }


              
        } else {
            lprintf("Non GET request...\r\nRequest:\r\n%s\r\n", data);
        }

        pbuf_free(p);
    }

    else {
        /* No data arrived */
        /* That means the client closes the connection and sent us a packet with FIN flag set to 1. */
        /* We have to cleanup and destroy out TCPConnection. */
        lprintf("Connection closed by client.\r\n");
        pbuf_free(p);
    }
    /* Don't panic! Everything is fine. */
    return ERR_OK;
}
/* Accept an incomming call on the registered port */
err_t accept_callback(void *arg, struct tcp_pcb *npcb, err_t err) {
    LWIP_UNUSED_ARG(arg);
    /* Subscribe a receive callback function */
    tcp_recv(npcb, &recv_callback);
    /* Don't panic! Everything is fine. */
    return ERR_OK;
}

void network_init(void)
{
    lprintf("l\r\nNetwork Starting Up...\r\n");
    stage = 0;
    struct netif   *netif = &netif_data;
    struct ip_addr  ipaddr;
    struct ip_addr  netmask;
    struct ip_addr  gateway;
    Ticker tickFast, tickSlow, tickARP, eth_tick, dns_tick, dhcp_coarse, dhcp_fine;
//    stage_blinker.attach_us(&stageblinker, 1000*500);

    char *hostname = "my-mbed";

    lprintf("Configuring device for DHCP...\r\n");
    /* Start Network with DHCP */
    IP4_ADDR(&netmask, 255,255,255,255);
    IP4_ADDR(&gateway, 0,0,0,0);
    IP4_ADDR(&ipaddr, 0,0,0,0);
    /* Initialise after configuration */
    lwip_init();
    netif->hwaddr_len = ETHARP_HWADDR_LEN;
    device_address((char *)netif->hwaddr);
    netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, device_init, ip_input);
    netif->hostname = hostname;
    netif_set_default(netif);
    dhcp_start(netif); // <-- Use DHCP

    /* Initialise all needed timers */
    tickARP.attach_us( &etharp_tmr,  ARP_TMR_INTERVAL  * 1000);
    tickFast.attach_us(&tcp_fasttmr, TCP_FAST_INTERVAL * 1000);
    tickSlow.attach_us(&tcp_slowtmr, TCP_SLOW_INTERVAL * 1000);
    dns_tick.attach_us(&dns_tmr, DNS_TMR_INTERVAL * 1000);
    dhcp_coarse.attach_us(&dhcp_coarse_tmr, DHCP_COARSE_TIMER_MSECS * 1000);
    dhcp_fine.attach_us(&dhcp_fine_tmr, DHCP_FINE_TIMER_MSECS * 1000);
    stage = 1; 
    while (!netif_is_up(netif)) {
        device_poll();
    }

    /*
        while (!(netif->dhcp->state == DHCP_BOUND || netif->dhcp->state == DHCP_PERMANENT))
        {
            ledLink = ethernet.link();
            device_poll();
            //printf("Waiting for DHCP response, state = %d\r\n", netif->dhcp->state);
            //wait_ms(100);
            }
        */
    stage = 2;
    lprintf("Interface %02x.%02x.%02x.%02x.%02x.%02x is up, local IP is %s\r\n",
            (char*) netif->hwaddr[0],
            (char*) netif->hwaddr[1],
            (char*) netif->hwaddr[2],
            (char*) netif->hwaddr[3],
            (char*) netif->hwaddr[4],
            (char*) netif->hwaddr[5],
           inet_ntoa(*(struct in_addr*)&(netif->ip_addr)));

    lprintf("Starting Web Server...\r\n");

    /* Bind a function to a tcp port */
    struct tcp_pcb *pcb = tcp_new();
    if (tcp_bind(pcb, IP_ADDR_ANY, 80) == ERR_OK) {
        pcb = tcp_listen(pcb);
        tcp_accept(pcb, &accept_callback);
    }
    net_state = 1;
    
    lprintf("Waiting for connection...\n");
}

void network_test(void) 
{
    led_on(2);
    device_poll();
    ethernet.link();
    led_off(2);
}