d7b3770640bba46325eb82dc66afdff3c4ebbe93
[bertos.git] / boards / sam3x-ek / examples / sam3x-ek_http_server / main.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2010,2011 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \author Andrea Righi <arighi@develer.com>
34  *
35  * \brief lwIP TCP/IP echo server listening on port 80.
36  */
37
38 #include "bertos.c"
39
40 #include "hw/hw_sd.h"
41 #include "hw/hw_adc.h"
42 #include "hw/hw_sdram.h"
43
44 #include <cfg/debug.h>
45
46 #include <cpu/irq.h>
47 #include <cpu/power.h>
48
49 #include <drv/timer.h>
50 #include <drv/ser.h>
51 #include <drv/sd.h>
52 #include <drv/dmac_sam3.h>
53 #include <drv/adc.h>
54
55 #include <kern/proc.h>
56 #include <kern/monitor.h>
57
58 #include <netif/ethernetif.h>
59
60 #include <lwip/ip.h>
61 #include <lwip/ip_addr.h>
62 #include <lwip/netif.h>
63 #include <lwip/tcpip.h>
64 #include <lwip/dhcp.h>
65
66 #include <fs/fat.h>
67
68 #include <stdio.h>
69 #include <string.h>
70
71 /* Network interface global variables */
72 static struct ip_addr ipaddr, netmask, gw;
73 static struct netif netif;
74
75 // SD fat filesystem context
76 static Sd sd;
77 static FATFS fs;
78 static FatFile in_file;
79
80 typedef struct BoardStatus
81 {
82         char local_ip[sizeof("123.123.123.123")];
83         char last_connected_ip[sizeof("123.123.123.123")];
84         uint16_t internal_temp;
85         ticks_t up_time;
86         size_t tot_req;
87 } BoardStatus;
88
89 static BoardStatus status;
90
91 static void init(void)
92 {
93         /* Enable all the interrupts */
94         IRQ_ENABLE;
95
96         /* Initialize debugging module (allow kprintf(), etc.) */
97         kdbg_init();
98         /* Initialize system timer */
99         timer_init();
100
101         /*
102          * Kernel initialization: processes (allow to create and dispatch
103          * processes using proc_new()).
104          */
105         proc_init();
106         sdram_init();
107
108         /* Initialize TCP/IP stack */
109         tcpip_init(NULL, NULL);
110
111         /* Bring up the network interface */
112         netif_add(&netif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, tcpip_input);
113         netif_set_default(&netif);
114         netif_set_up(&netif);
115
116         dmac_init();
117
118         adc_init();
119         /* Enable the adc to read internal temperature sensor */
120         hw_enableTempRead();
121 }
122
123 static NORETURN void status_process(void)
124 {
125         while (1)
126         {
127                 status.internal_temp = hw_convertToDegree(adc_read(ADC_TEMPERATURE_CH));
128                 status.up_time++;
129                 timer_delay(1000);
130         }
131 }
132
133 static void get_fileName(char *revc_buf, char *name, size_t len)
134 {
135         char *p = strstr(revc_buf, "GET");
136         if (p)
137         {
138                 //skip the "/" in get string request
139                 p += sizeof("GET") + 1;
140                 for (size_t i = 0; *p != ' '; i++,p++)
141                 {
142                         if (i > len)
143                                 break;
144                         name[i] = *p;
145                 }
146         }
147 }
148
149 static const char http_html_hdr_200[] = "HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n";
150 static const char http_html_hdr_404[] = "HTTP/1.1 404 Not Found\r\nContent-type: text/html\r\n\r\n";
151
152 static const char http_file_not_found[] = "\
153 <!DOCTYPE html PUBLIC \"-//IETF//DTD HTML 2.0//EN\"> \
154 <html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\"> \
155 <title>404 Not Found</title></head><body><img src=\"bertos_jpg.jpg\"><h1>404 Not Found</h1>\
156 <p>The requested URL was not found on this server.</p><hr>\
157 <address>BeRTOS simple HTTP server</address></body></html>";
158
159
160 static const char http_sd_not_present[] = " \
161 <!DOCTYPE html PUBLIC \"-//IETF//DTD HTML 2.0//EN\">  \
162 <html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">  \
163 <title>BeRTOS simple HTTP Server</title></head><body><img src=\"bertos_jpg.jpg\"> \
164 <h1>BeRTOS simple HTTP Server</h1><p>Simple Http server, the site's pages are stored on SD card, check it if is present.</p><hr>\
165 <a href=\"http://www.bertos.org\">www.BeRTOS.org</a></body></html> \
166 ";
167
168 static uint8_t tx_buf[2048];
169
170 #define IP_ADDR_TO_INT_TUPLE(addr) \
171                 (int)((addr) >>  0 & 0xff), \
172                 (int)((addr) >>  8 & 0xff), \
173                 (int)((addr) >> 16 & 0xff), \
174                 (int)((addr) >> 24 & 0xff)
175
176
177 static char file_name[80];
178 int main(void)
179 {
180         struct netconn *server;
181         FRESULT result;
182
183         /* Hardware initialization */
184         init();
185
186         proc_new(status_process, NULL, KERN_MINSTACKSIZE * 2, NULL);
187
188         dhcp_start(&netif);
189         while (!netif.ip_addr.addr)
190                 timer_delay(DHCP_FINE_TIMER_MSECS);
191         kprintf("dhcp ok: ip = %d.%d.%d.%d\n", IP_ADDR_TO_INT_TUPLE(netif.ip_addr.addr));
192
193         server = netconn_new(NETCONN_TCP);
194         netconn_bind(server, IP_ADDR_ANY, 80);
195         netconn_listen(server);
196
197         while (1)
198         {
199                 struct netconn *client;
200                 struct netbuf *rx_buf_conn;
201                 char *rx_buf;
202                 u16_t len;
203
204                 client = netconn_accept(server);
205                 if (!client)
206                         continue;
207
208                 //Update board status.
209                 sprintf(status.last_connected_ip, "%d.%d.%d.%d", IP_ADDR_TO_INT_TUPLE(client->pcb.ip->remote_ip.addr));
210                 sprintf(status.local_ip, "%d.%d.%d.%d", IP_ADDR_TO_INT_TUPLE(client->pcb.ip->local_ip.addr));
211                 status.tot_req++;
212
213                 rx_buf_conn = netconn_recv(client);
214                 if (rx_buf_conn)
215                 {
216                         netbuf_data(rx_buf_conn, (void **)&rx_buf, &len);
217                         if (rx_buf)
218                         {
219                                 memset(file_name, 0, sizeof(file_name));
220                                 memset(tx_buf, 0, sizeof(tx_buf));
221
222                                 get_fileName(rx_buf, file_name, sizeof(file_name));
223
224                                 kprintf("%s\n", file_name);
225                                 if (strlen(file_name) == 0)
226                                         strcpy(file_name, "index.htm");
227
228                                 if (!strcmp("bertos_jpg.jpg", file_name))
229                                 {
230                                         netconn_write(client, bertos_jpg, sizeof(bertos_jpg), NETCONN_NOCOPY);
231                                 }
232                                 else if (!strcmp("status", file_name))
233                                 {
234                                         sprintf((char *)tx_buf, "[ %s, %s, %d.%d, %ld, %d ]", status.local_ip, status.last_connected_ip,
235                                                                                                                                 status.internal_temp / 10, status.internal_temp % 10,
236                                                                                                                                 status.up_time, status.tot_req);
237
238                                         netconn_write(client, tx_buf, strlen((char *)tx_buf), NETCONN_COPY);
239                                 }
240                                 else if (SD_CARD_PRESENT())
241                                 {
242                                         bool sd_ok = sd_init(&sd, NULL, 0);
243                                         if (sd_ok)
244                                         {
245                                                 kprintf("Mount FAT filesystem.\n");
246                                                 result = f_mount(0, &fs);
247                                                 if (result != FR_OK)
248                                                 {
249                                                         kprintf("Mounting FAT volumes error[%d]\n", result);
250                                                         sd_ok = false;
251                                                         f_mount(0, NULL);
252                                                 }
253
254                                                 if (sd_ok)
255                                                 {
256                                                         result = fatfile_open(&in_file, file_name,  FA_OPEN_EXISTING | FA_READ);
257
258                                                         size_t count = 0;
259                                                         if (result == FR_OK)
260                                                         {
261                                                                 kprintf("Opened file '%s' size %ld\n", file_name, in_file.fat_file.fsize);
262
263                                                                 netconn_write(client, http_html_hdr_200, sizeof(http_html_hdr_200) - 1, NETCONN_NOCOPY);
264
265                                                                 while (count < in_file.fat_file.fsize)
266                                                                 {
267                                                                         int len = kfile_read(&in_file.fd, tx_buf, sizeof(tx_buf));
268                                                                         netconn_write(client, tx_buf, len, NETCONN_COPY);
269                                                                         count += len;
270                                                                 }
271
272                                                                 kfile_flush(&in_file.fd);
273                                                                 kfile_close(&in_file.fd);
274
275                                                                 kprintf("Sent: %d\n", count);
276                                                         }
277                                                         else
278                                                         {
279                                                                 kprintf("Unable to open file: '%s' error[%d]\n",  file_name, result);
280                                                                 netconn_write(client, http_html_hdr_404, sizeof(http_html_hdr_404) - 1, NETCONN_NOCOPY);
281                                                                 netconn_write(client, http_file_not_found, sizeof(http_file_not_found) - 1, NETCONN_NOCOPY);
282                                                         }
283                                                 }
284                                         }
285                                         f_mount(0, NULL);
286                                         kprintf("Umount FAT filesystem.\n");
287                                 }
288                                 else
289                                 {
290                                         netconn_write(client, http_html_hdr_404, sizeof(http_html_hdr_404) - 1, NETCONN_NOCOPY);
291                                         netconn_write(client, http_sd_not_present, sizeof(http_sd_not_present), NETCONN_NOCOPY);
292                                 }
293                         }
294                         netconn_close(client);
295                         netbuf_delete(rx_buf_conn);
296                 }
297                 netconn_delete(client);
298         }
299 }